From d49d519f86098894f586fb3669715c1667373e41 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 21:15:03 -0400 Subject: [PATCH 001/140] README --- README | 1 + 1 file changed, 1 insertion(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..616b35f --- /dev/null +++ b/README @@ -0,0 +1 @@ +Workflow Description Language From ef214714f21870862139391aad05880fd468e25e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 21:17:47 -0400 Subject: [PATCH 002/140] prototype language definition --- grammars/wdl.zgr | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 grammars/wdl.zgr diff --git a/grammars/wdl.zgr b/grammars/wdl.zgr new file mode 100644 index 0000000..90f018b --- /dev/null +++ b/grammars/wdl.zgr @@ -0,0 +1,26 @@ +{ + "ll1": { + "start": "wdl", + "rules": [ + "wdl := list(wdl_entity)", + "wdl_entity := workflow | step", + "workflow := 'workflow' + 'identifier' + 'lbrace' + workflow_body + 'rbrace' -> Workflow( name=$1, body=$3 )", + "workflow_body := list(workflow_step)", + "workflow_step := 'step' + 'identifier' + 'colon' + workflow_step_output + 'identifier' + workflow_step_input + 'semi' -> WorkflowStep( name=$1, step=$4, input=$5, output=$3 )", + "workflow_step_input := 'lparen' + list(workflow_step_input_param, 'comma') + 'rparen' -> $1", + "workflow_step_input_param := 'string_literal' -> String(val=$0) | 'file' + 'lparen' + 'string_literal' + 'rparen' -> File(path=$2) | 'identifier' -> Variable(name=$0)", + "workflow_step_output := 'lparen' + list(workflow_step_output_param, 'comma') + 'rparen' + 'equals' -> $1 | _empty", + "workflow_step_output_param := 'identifier' -> Output(var=$0)", + "step := 'step' + 'identifier' + 'lparen' + list(step_parameter, 'comma') + 'rparen' + 'lbrace' + step_body + 'rbrace' -> Step(name=$1, parameters=$3, body=$6)", + "step_parameter := 'identifier' + 'colon' + step_parameter_type -> StepInputParameter(name=$0, type=$2)", + "step_parameter_type := 'file' | 'string'", + "step_body := list(step_body_spec)", + "step_body_spec := step_action | step_output", + "step_action := 'action' + 'colon' + step_action_sub + 'semi' -> $2", + "step_action_sub := step_action_command | step_action_scatter_gather", + "step_action_command := 'command' + 'lparen' + 'string_literal' + 'rparen' -> CommandAction( cmd=$2 )", + "step_action_scatter_gather := 'scatter_gather' + 'lparen' + 'identifier' + 'comma' + 'identifier' + 'comma' + 'identifier' + 'rparen' -> ScatterGatherAction(prepare=$2, scatter=$4, gather=$6)", + "step_output := 'output' + 'colon' + list(workflow_step_input_param, 'comma') + 'semi' -> StepOutputParameters( parameters=$2 )" + ] + } +} From f98d9bd32f68e81c362ba927b839582fb88a2e26 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 21:19:12 -0400 Subject: [PATCH 003/140] three examples --- grammars/1.wdl | 1 + grammars/2.wdl | 3 +++ grammars/3.wdl | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 grammars/1.wdl create mode 100644 grammars/2.wdl create mode 100644 grammars/3.wdl diff --git a/grammars/1.wdl b/grammars/1.wdl new file mode 100644 index 0000000..8be4dfc --- /dev/null +++ b/grammars/1.wdl @@ -0,0 +1 @@ +workflow name {} diff --git a/grammars/2.wdl b/grammars/2.wdl new file mode 100644 index 0000000..3ebef1e --- /dev/null +++ b/grammars/2.wdl @@ -0,0 +1,3 @@ +workflow name { + step PreprocessNormal: (normal_pp_bam) = PreprocessBam( File("normal.bam"), "xyz" ); +} diff --git a/grammars/3.wdl b/grammars/3.wdl new file mode 100644 index 0000000..4292246 --- /dev/null +++ b/grammars/3.wdl @@ -0,0 +1,24 @@ +workflow SomeAnalysisWorkflow { + step PreprocessNormal: (normal_pp_bam) = PreprocessBam( File("normal.bam"), "xyz" ); + step PreprocessTumor: (tumor_pp_bam) = PreprocessBam( File("tumor.bam"), "abc" ); + step DoAnalysis: (analysis_file, str) = DoAnalysis(normal_pp_bam, tumor_pp_bam); + step GenerateReport: GenerateReport(); +} + +step PreprocessBam(input_bam:File, option:String) { + output: File("preprocessed.bam"); + action: command("python ${libdir}preprocess.py ${input_bam} --with-option=${option}"); +} + +step DoAnalysis(normal_bam:File, tumor_bam:File) { + output: File("dir/analysis.txt"), "static string"; + action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); +} + +step GenerateReport() { + action: command("Rscript ${libdir}report.R"); +} + +step ScatterGatherStep() { + action: scatter-gather(prepare, scatter, gather); +} From 56ec31bfe1b1891a751180339ebd3970d240ca4c Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 21:22:09 -0400 Subject: [PATCH 004/140] prototype Hermes generated parser --- grammars/Lexer.py | 358 ++++++++++++++++++++++++ grammars/ParserCommon.py | 210 ++++++++++++++ grammars/ParserMain.py | 49 ++++ grammars/test.sh | 1 + grammars/wdl_Parser.py | 708 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1326 insertions(+) create mode 100644 grammars/Lexer.py create mode 100644 grammars/ParserCommon.py create mode 100644 grammars/ParserMain.py create mode 100644 grammars/test.sh create mode 100644 grammars/wdl_Parser.py diff --git a/grammars/Lexer.py b/grammars/Lexer.py new file mode 100644 index 0000000..a1d4ad6 --- /dev/null +++ b/grammars/Lexer.py @@ -0,0 +1,358 @@ +import re, sys, base64, json +from collections import OrderedDict +from wdl_Parser import wdl_Parser + +def token(string, lineno, colno, terminalId, lexer): + lexer.addToken(Token(terminalId, lexer.resource, wdl_Parser.terminals[terminalId], string, lineno, colno)) + +class SourceCode: + def __init__(self, resource, fp, line = 1, column = 1): + self.__dict__.update(locals()) + self.sourceCode = fp.read() + fp.close() + + def getResource(self): + return self.resource + + def getString(self): + return self.sourceCode + + def getColumn(self): + return self.column + + def getLine(self): + return self.line + + def __str__(self): + return '' % (self.resource) + +class Token: + def __init__(self, id, resource, terminal_str, source_string, lineno, colno): + self.__dict__.update(locals()) + + def getString(self): + return self.source_string + + def getLine(self): + return self.lineno + + def getColumn(self): + return self.colno + + def getId(self): + return self.id + + def getTerminalStr(self): + return self.terminal_str + + def getResource(self): + return self.resource + + def toAst(self): + return self + + def __str__( self ): + return json.dumps(self.json()) + + def json(self): + return OrderedDict([ + ('terminal', self.terminal_str.lower()), + ('line', self.lineno), + ('col', self.colno), + ('resource', self.resource), + ('source_string', base64.b64encode(self.source_string.encode('utf-8')).decode('utf-8')) + ]) + +class Cursor: + def __init__(self): + self.string = '' + self.lineno = 1 + self.colno = 1 + c = lambda x: c_Parser.terminals[x] + self.insertSpaceAfter = { + c('else') + } + + def add(self, token): + if token.lineno > self.lineno: + self.string += ''.join('\n' for i in range(token.lineno - self.lineno)) + self.lineno = token.lineno + self.colno = 1 + if token.colno > self.colno: + self.string += ''.join(' ' for i in range(token.colno - self.colno)) + self.colno = token.colno + self.string += token.source_string + if token.fromPreprocessor or token.id in self.insertSpaceAfter: + self.string += ' ' + self.colno += len(token.source_string) + def __str__(self): + return self.string + +class SourceCodeWriter: + def __init__(self, tokenList, parsetree=None, grammar=None, ast=None, theme=None, highlight=False): + self.__dict__.update(locals()) + self.string = '' + self.lineno = 1 + self.colno = 1 + self.ancestors = dict([(t, set()) for t in self.tokenList]) + self.parents = dict([(t, set()) for t in self.tokenList]) + self.getTokenAncestors(ast) + self.termcolor = XTermColorMap() + c = lambda x: c_Parser.terminals[x] + self.insertSpaceAfter = { + c('else') + } + + # bah, cruft + self.keywords = [] + + def getTokenAncestors(self, ast): + self.stack = [] + self._getTokenAncestors(ast) + + def _getTokenAncestors(self, ast): + if not ast: + return + self.stack.append(ast.name) + for (attr, obj) in ast.attributes.items(): + if isinstance(obj, Token): + self.ancestors[obj] = self.ancestors[obj].union(set(self.stack)) + self.parents[obj] = (self.stack[-1], attr) + elif isinstance(obj, Ast): + self._getTokenAncestors(obj) + elif isinstance(obj, list): + for x in obj: + if isinstance(x, Token): + self.ancestors[x] = self.ancestors[x].union(set(self.stack)) + self.parents[x] = (self.stack[-1], attr) + else: + self._getTokenAncestors(x) + self.stack.pop() + + def add(self, token): + if token.lineno > self.lineno: + self.string += ''.join('\n' for i in range(token.lineno - self.lineno)) + self.lineno = token.lineno + self.colno = 1 + if token.colno > self.colno: + self.string += ''.join(' ' for i in range(token.colno - self.colno)) + self.colno = token.colno + + self.string += self.doHighlight(token) + + if token.fromPreprocessor or token.id in self.insertSpaceAfter: + self.string += ' ' + self.colno += len(token.source_string) + + def doHighlight(self, token): + if not self.highlight: + return token.source_string + + if token in self.parents and len(self.parents[token]): + (parent, attr) = self.parents[token] + if attr == 'declaration_specifiers': + return self.termcolor.colorize(token.source_string, 0x0087ff) + if parent == 'FuncCall' and attr == 'name': + return self.termcolor.colorize(token.source_string, 0x8700ff) + if parent == 'FunctionSignature' and attr == 'declarator': + return self.termcolor.colorize(token.source_string, 0xff8700) + if self.grammar: + if not len(self.keywords): + for rule in self.grammar.getRules(): + terminal = rule.isTokenAlias() + if terminal and rule.nonterminal.string == 'keyword': + self.keywords.append(terminal.string) + if token.terminal_str in self.keywords: + return self.termcolor.colorize(token.source_string, 0xffff00) + if token.terminal_str == 'string_literal': + return self.termcolor.colorize(token.source_string, 0xff0000) + if token.terminal_str == 'identifier': + return self.termcolor.colorize(token.source_string, 0x00ff00) + + return token.source_string + + def __str__(self): + if not len(self.string): + for token in self.tokenList: + self.add(token) + return self.string + +class TokenList(list): + def __init__(self, arg1=[]): + super().__init__(arg1) + self.isIter = False + def __iter__(self): + if self.isIter == False: + self.index = 0 + isIter = True + return self + def __next__(self): + try: + rval = self[self.index] + self.index += 1 + return rval + except: + raise StopIteration + def reset(self): + self.isIter = False + def peek(self, whereto): + try: + return self[self.index + int(whereto)] + except: + return None + def go(self, whereto): + whereto = int(whereto) + if self.index + whereto < 0 or self.index + whereto + 1 > len(self): + raise Exception() + self.index += whereto + return self + def check(self, whereto, ids): + try: + return self[self.index + int(whereto) - 1].id in ids + except: + return False + def toString(self, parsetree=None, grammar=None, ast=None, theme=None, highlight=False): + kwargs = locals() + del kwargs['self'] + scw = SourceCodeWriter(self, **kwargs) + return str(scw) + cursor = Cursor() + for token in self: + cursor.add( token ) + return str(cursor) + +class Lexer: + def __iter__(self): + return self + + def __next__(self): + raise StopIteration() + +class StatelessPatternMatchingLexer(Lexer): + def __init__(self, regex): + self.__dict__.update(locals()) + def match(self, string, wholeStringOnly=False): + for (regex, terminalId, function) in self.regex: + match = regex.match(string) + if match: + sourceString = match.group(0) + if wholeStringOnly and sourceString != string: + continue + return (sourceString, terminalId, function) + return (None, None, None) + +class PatternMatchingLexer(StatelessPatternMatchingLexer): + def __init__(self, sourceCode, regex): + self.__dict__.update(locals()) + self.string = sourceCode.getString() + self.resource = sourceCode.getResource() + self.colno = sourceCode.getColumn() + self.lineno = sourceCode.getLine() + self.cache = [] + + def addToken(self, token): + self.cache.append(token) + + def addTokens(self, tokens): + self.cache.extend(tokens) + + def hasToken(self): + return len(self.cache) > 0 + + def nextToken(self): + if not self.hasToken(): + return None + token = self.cache[0] + self.cache = self.cache[1:] + return token + + def advance(self, string): + self.string = self.string[len(string):] + newlines = len(list(filter(lambda x: x == '\n', string))) + self.lineno += newlines + if newlines > 0: + self.colno = len(string.split('\n')[-1]) + 1 + else: + self.colno += len(string) + + def peek(self, n=1): + # returns an n-item list of tuples: (terminalId, length) + lookahead = list() + loc = 0 + for i in range(n): + current = self.string[loc:] + if not len(current): + return lookahead + for (regex, terminalId, function) in self.regex: + match = regex.match(current) + if match: + length = len(match.group(0)) + loc += length + lookahead.append( (terminalId,match.group(0),) ) + return lookahead + + def nextMatch(self): + activity = True + while activity: + activity = False + if not len(self.string): + raise StopIteration() + (string, terminalId, function) = self.match(self.string) + if string is not None: + activity = True + lineno = self.lineno + colno = self.colno + self.advance( string ) + if function: + function(string, lineno, colno, terminalId, self) + return self.nextToken() + return None + + def __iter__(self): + return self + + def __next__(self): + if self.hasToken(): + token = self.nextToken() + return token + if len(self.string.strip()) <= 0: + raise StopIteration() + token = self.nextMatch() + if not token: + error = 'Invalid character on line %d, col %d' % (self.lineno, self.colno) + raise Exception(error) + return token + +class wdlLexer(PatternMatchingLexer): + regex = [ + ( re.compile(r'scatter-gather(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_SCATTER_GATHER, token ), + ( re.compile(r'String(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_STRING, token ), + ( re.compile(r'workflow(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_WORKFLOW, token ), + ( re.compile(r'File(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_FILE, token ), + ( re.compile(r'output(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_OUTPUT, token ), + ( re.compile(r'step(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_STEP, token ), + ( re.compile(r'command(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_COMMAND, token ), + ( re.compile(r'action(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_ACTION, token ), + ( re.compile(r','), wdl_Parser.TERMINAL_COMMA, token ), + ( re.compile(r':'), wdl_Parser.TERMINAL_COLON, token ), + ( re.compile(r'}'), wdl_Parser.TERMINAL_RBRACE, token ), + ( re.compile(r';'), wdl_Parser.TERMINAL_SEMI, token ), + ( re.compile(r'{'), wdl_Parser.TERMINAL_LBRACE, token ), + ( re.compile(r'='), wdl_Parser.TERMINAL_EQUALS, token ), + ( re.compile(r'\('), wdl_Parser.TERMINAL_LPAREN, token ), + ( re.compile(r'\)'), wdl_Parser.TERMINAL_RPAREN, token ), + ( re.compile(r'"([^\\\"\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"'), wdl_Parser.TERMINAL_STRING_LITERAL, token ), + ( re.compile(r'([a-zA-Z_]|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*'), wdl_Parser.TERMINAL_IDENTIFIER, token ), + ( re.compile(r'[ \t\n]+', 0), None, None ) + ] + + def __init__(self): + super(wdlLexer, self).__init__(SourceCode('/dev/stdin', sys.stdin), self.regex) + +if __name__ == '__main__': + lex = wdlLexer() + tokens = list(lex) + print('[') + for (i, token) in enumerate(tokens): + print(' {}{}'.format(token, ',' if i != len(tokens) - 1 else '')) + print(']') diff --git a/grammars/ParserCommon.py b/grammars/ParserCommon.py new file mode 100644 index 0000000..c194523 --- /dev/null +++ b/grammars/ParserCommon.py @@ -0,0 +1,210 @@ +import json, base64 +from collections import OrderedDict +class Terminal: + def __init__(self, id, str, base64_source_string, resource, line, col): + self.__dict__.update(locals()) + def getId(self): + return self.id + def toAst(self): + return self + def __str__( self ): + return json.dumps(self.json()) + def json(self): + return OrderedDict([ + ('terminal', self.str.lower()), + ('line', self.line), + ('col', self.col), + ('resource', self.resource), + ('source_string', self.base64_source_string) + ]) + def __str__(self): + return json.dumps(self.json()) +class NonTerminal(): + def __init__(self, id, str): + self.__dict__.update(locals()) + self.list = False + def __str__(self): + return self.str +class AstTransform: + pass +class AstTransformSubstitution(AstTransform): + def __init__(self, idx): + self.__dict__.update(locals()) + def __repr__(self): + return '$' + str(self.idx) + def __str__(self): + return self.__repr__() +class AstTransformNodeCreator(AstTransform): + def __init__( self, name, parameters ): + self.__dict__.update(locals()) + def __repr__( self ): + return self.name + '( ' + ', '.join(['%s=$%s' % (k,str(v)) for k,v in self.parameters.items()]) + ' )' + def __str__(self): + return self.__repr__() +class AstList(list): + def toAst(self): + retval = [] + for ast in self: + retval.append(ast.toAst()) + return retval +class ParseTree(): + def __init__(self, nonterminal): + self.__dict__.update(locals()) + self.children = [] + self.astTransform = None + self.isExpr = False + self.isNud = False + self.isPrefix = False + self.isInfix = False + self.nudMorphemeCount = 0 + self.isExprNud = False # true for rules like _expr := {_expr} + {...} + self.listSeparator = None + self.list = False + def add( self, tree ): + self.children.append( tree ) + def toAst( self ): + if self.list == 'slist' or self.list == 'nlist': + if len(self.children) == 0: + return AstList() + offset = 1 if self.children[0] == self.listSeparator else 0 + r = AstList([self.children[offset].toAst()]) + r.extend(self.children[offset+1].toAst()) + return r + elif self.list == 'tlist': + if len(self.children) == 0: + return AstList() + r = AstList([self.children[0].toAst()]) + r.extend(self.children[2].toAst()) + return r + elif self.list == 'mlist': + r = AstList() + if len(self.children) == 0: + return r + lastElement = len(self.children) - 1 + for i in range(lastElement): + r.append(self.children[i].toAst()) + r.extend(self.children[lastElement].toAst()) + return r + elif self.isExpr: + if isinstance(self.astTransform, AstTransformSubstitution): + return self.children[self.astTransform.idx].toAst() + elif isinstance(self.astTransform, AstTransformNodeCreator): + parameters = {} + for name, idx in self.astTransform.parameters.items(): + if idx == '$': + child = self.children[0] + elif isinstance(self.children[0], ParseTree) and \ + self.children[0].isNud and \ + not self.children[0].isPrefix and \ + not self.isExprNud and \ + not self.isInfix: + if idx < self.children[0].nudMorphemeCount: + child = self.children[0].children[idx] + else: + index = idx - self.children[0].nudMorphemeCount + 1 + child = self.children[index] + elif len(self.children) == 1 and not isinstance(self.children[0], ParseTree) and not isinstance(self.children[0], list): + return self.children[0] + else: + child = self.children[idx] + parameters[name] = child.toAst() + return Ast(self.astTransform.name, parameters) + else: + if isinstance(self.astTransform, AstTransformSubstitution): + return self.children[self.astTransform.idx].toAst() + elif isinstance(self.astTransform, AstTransformNodeCreator): + parameters = {name: self.children[idx].toAst() for name, idx in self.astTransform.parameters.items()} + return Ast(self.astTransform.name, parameters) + elif len(self.children): + return self.children[0].toAst() + else: + return None + def __str__( self ): + children = [] + for child in self.children: + if isinstance(child, list): + children.append('[' + ', '.join([str(a) for a in child]) + ']') + else: + children.append(str(child)) + return '(' + str(self.nonterminal) + ': ' + ', '.join(children) + ')' +class Ast(): + def __init__(self, name, attributes): + self.__dict__.update(locals()) + def getAttr(self, attr): + return self.attributes[attr] + def __str__(self): + return '(%s: %s)' % (self.name, ', '.join('%s=%s'%(str(k), '[' + ', '.join([str(x) for x in v]) + ']' if isinstance(v, list) else str(v) ) for k,v in self.attributes.items())) +def noColor(string, color): + return string +def termColor(string, intcolor): + return "\033[38;5;%dm%s\033[0m" % (intcolor, string) +class AstPrettyPrintable: + def __init__(self, ast, color=False): + self.__dict__.update(locals()) + def getAttr(self, attr): + return self.ast.getAttr(attr) + def __str__(self): + return self._prettyPrint(self.ast, 0) + def _prettyPrint(self, ast, indent = 0): + indentStr = ''.join([' ' for x in range(indent)]) + colored = noColor + if self.color: + colored = termColor + if isinstance(ast, Ast): + string = '%s(%s:\n' % (indentStr, colored(ast.name, 12)) + string += ',\n'.join([ \ + '%s %s=%s' % (indentStr, colored(name, 10), self._prettyPrint(value, indent + 2).lstrip()) for name, value in ast.attributes.items() \ + ]) + string += '\n%s)' % (indentStr) + return string + elif isinstance(ast, list): + if len(ast) == 0: + return '%s[]' % (indentStr) + string = '%s[\n' % (indentStr) + string += ',\n'.join([self._prettyPrint(element, indent + 2) for element in ast]) + string += '\n%s]' % (indentStr) + return string + elif isinstance(ast, Terminal): + return '%s%s' % (indentStr, colored(str(ast), 9)) + else: + return '%s%s' % (indentStr, colored(str(ast), 9)) +class ParseTreePrettyPrintable: + def __init__(self, ast, color=False): + self.__dict__.update(locals()) + def __str__(self): + return self._prettyPrint(self.ast, 0) + def _prettyPrint(self, parsetree, indent = 0): + colored = noColor + if self.color: + colored = termColor + indentStr = ''.join([' ' for x in range(indent)]) + if isinstance(parsetree, ParseTree): + if len(parsetree.children) == 0: + return '(%s: )' % (colored(parsetree.nonterminal, 10)) + string = '%s(%s:\n' % (indentStr, colored(parsetree.nonterminal, 10)) + string += ',\n'.join([ \ + '%s %s' % (indentStr, self._prettyPrint(value, indent + 2).lstrip()) for value in parsetree.children \ + ]) + string += '\n%s)' % (indentStr) + return string + elif isinstance(parsetree, Terminal): + return '%s%s' % (indentStr, colored(str(parsetree), 9)) + else: + return '%s%s' % (indentStr, colored(parsetree, 9)) +class SyntaxError(Exception): + def __init__(self, message): + self.__dict__.update(locals()) + def __str__(self): + return self.message +class TokenStream(list): + def __init__(self, arg): + super().__init__(arg) + self.index = 0 + def advance(self): + self.index += 1 + return self.current() + def current(self): + try: + return self[self.index] + except IndexError: + return None diff --git a/grammars/ParserMain.py b/grammars/ParserMain.py new file mode 100644 index 0000000..696ee62 --- /dev/null +++ b/grammars/ParserMain.py @@ -0,0 +1,49 @@ +import sys, json, traceback, base64 +from ParserCommon import * +from wdl_Parser import wdl_Parser +def getParser(name): + if name == 'wdl': + return wdl_Parser() + raise Exception('Invalid grammar name: {}'.format(name)) +if __name__ == '__main__': + grammars = "wdl" + if len(sys.argv) < 2: + print("Usage: {} <{}> ".format(sys.argv[0], grammars)) + sys.exit(-1) + grammar = sys.argv[1].lower() + parser = getParser(grammar) + in_tokens = json.loads(sys.stdin.read()) + tokens = [] + for token in in_tokens: + + for key in ["terminal", "line", "col", "resource", "source_string"]: + if key not in token.keys(): + raise Exception('Malformed token (missing key {0}): {1}'.format(key, json.dumps(token))) + + try: + tokens.append(Terminal( + parser.terminals[token['terminal']], + token['terminal'], + token['source_string'], + token['resource'], + token['line'], + token['col'] + )) + except AttributeError as error: + sys.stderr.write( str(error) + "\n" ) + sys.exit(-1) + + tokens = TokenStream(tokens) + + try: + parsetree = parser.parse( tokens ) + if len(sys.argv) > 2 and sys.argv[2] == 'ast': + ast = parsetree.toAst() + print(AstPrettyPrintable(ast, True)) + else: + print(ParseTreePrettyPrintable(parsetree, True)) + except SyntaxError as error: + exc_type, exc_value, exc_traceback = sys.exc_info() + traceback.print_tb(exc_traceback, file=sys.stdout) + sys.stderr.write( str(error) + "\n" ) + sys.exit(-1) diff --git a/grammars/test.sh b/grammars/test.sh new file mode 100644 index 0000000..4377a72 --- /dev/null +++ b/grammars/test.sh @@ -0,0 +1 @@ +cat 1.wdl | python Lexer.py | python ParserMain.py wdl ast diff --git a/grammars/wdl_Parser.py b/grammars/wdl_Parser.py new file mode 100644 index 0000000..1de0d9b --- /dev/null +++ b/grammars/wdl_Parser.py @@ -0,0 +1,708 @@ +import sys, inspect +from ParserCommon import * +def whoami(): + return inspect.stack()[1][3] +def whosdaddy(): + return inspect.stack()[2][3] +def parse( iterator, entry ): + p = wdl_Parser() + return p.parse(iterator, entry) +class wdl_Parser: + # Quark - finite string set maps one string to exactly one int, and vice versa + terminals = { + 0: 'comma', + 1: 'string_literal', + 2: 'scatter_gather', + 3: 'string', + 4: 'workflow', + 5: 'file', + 6: 'identifier', + 7: 'output', + 8: 'colon', + 9: 'rbrace', + 10: 'semi', + 11: 'step', + 12: 'lbrace', + 13: 'equals', + 14: 'lparen', + 15: 'command', + 16: 'action', + 17: 'rparen', + 'comma': 0, + 'string_literal': 1, + 'scatter_gather': 2, + 'string': 3, + 'workflow': 4, + 'file': 5, + 'identifier': 6, + 'output': 7, + 'colon': 8, + 'rbrace': 9, + 'semi': 10, + 'step': 11, + 'lbrace': 12, + 'equals': 13, + 'lparen': 14, + 'command': 15, + 'action': 16, + 'rparen': 17, + } + # Quark - finite string set maps one string to exactly one int, and vice versa + nonterminals = { + 18: 'step_body', + 19: 'workflow', + 20: 'step', + 21: 'step_body_spec', + 22: '_gen2', + 23: '_gen4', + 24: 'step_action_sub', + 25: 'step_action_scatter_gather', + 26: 'step_parameter_type', + 27: '_gen6', + 28: '_gen5', + 29: '_gen3', + 30: '_gen7', + 31: 'step_action_command', + 32: '_gen8', + 33: 'workflow_body', + 34: '_gen0', + 35: 'workflow_step_output', + 36: 'step_parameter', + 37: 'workflow_step_input', + 38: 'wdl', + 39: 'workflow_step_input_param', + 40: 'workflow_step_output_param', + 41: 'workflow_step', + 42: '_gen1', + 43: 'step_action', + 44: 'wdl_entity', + 45: 'step_output', + 'step_body': 18, + 'workflow': 19, + 'step': 20, + 'step_body_spec': 21, + '_gen2': 22, + '_gen4': 23, + 'step_action_sub': 24, + 'step_action_scatter_gather': 25, + 'step_parameter_type': 26, + '_gen6': 27, + '_gen5': 28, + '_gen3': 29, + '_gen7': 30, + 'step_action_command': 31, + '_gen8': 32, + 'workflow_body': 33, + '_gen0': 34, + 'workflow_step_output': 35, + 'step_parameter': 36, + 'workflow_step_input': 37, + 'wdl': 38, + 'workflow_step_input_param': 39, + 'workflow_step_output_param': 40, + 'workflow_step': 41, + '_gen1': 42, + 'step_action': 43, + 'wdl_entity': 44, + 'step_output': 45, + } + # table[nonterminal][terminal] = rule + table = [ + [-1, -1, -1, -1, -1, -1, -1, 3, -1, 3, -1, -1, -1, -1, -1, -1, 3, -1], + [-1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1], + [-1, 6, -1, -1, -1, 6, 6, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, 39], + [-1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21], + [-1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1], + [-1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, 18, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20], + [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25], + [9, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, 10], + [35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, 24, -1, 43, -1, -1, -1, -1, -1, -1, 24, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, 31, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1], + [-1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1], + [-1, 4, -1, -1, -1, 38, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, 2, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1], + [-1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + ] + TERMINAL_COMMA = 0 + TERMINAL_STRING_LITERAL = 1 + TERMINAL_SCATTER_GATHER = 2 + TERMINAL_STRING = 3 + TERMINAL_WORKFLOW = 4 + TERMINAL_FILE = 5 + TERMINAL_IDENTIFIER = 6 + TERMINAL_OUTPUT = 7 + TERMINAL_COLON = 8 + TERMINAL_RBRACE = 9 + TERMINAL_SEMI = 10 + TERMINAL_STEP = 11 + TERMINAL_LBRACE = 12 + TERMINAL_EQUALS = 13 + TERMINAL_LPAREN = 14 + TERMINAL_COMMAND = 15 + TERMINAL_ACTION = 16 + TERMINAL_RPAREN = 17 + def __init__(self, tokens=None): + self.__dict__.update(locals()) + self.expressionParsers = dict() + def isTerminal(self, id): + return 0 <= id <= 17 + def isNonTerminal(self, id): + return 18 <= id <= 45 + def parse(self, tokens): + self.tokens = tokens + self.start = 'WDL' + tree = self.parse_wdl() + if self.tokens.current() != None: + raise SyntaxError( 'Finished parsing without consuming all tokens.' ) + return tree + def expect(self, terminalId): + currentToken = self.tokens.current() + if not currentToken: + raise SyntaxError( 'No more tokens. Expecting %s' % (self.terminals[terminalId]) ) + if currentToken.getId() != terminalId: + raise SyntaxError( 'Unexpected symbol when parsing %s. Expected %s, got %s.' %(whosdaddy(), self.terminals[terminalId], currentToken if currentToken else 'None') ) + nextToken = self.tokens.advance() + if nextToken and not self.isTerminal(nextToken.getId()): + raise SyntaxError( 'Invalid symbol ID: %d (%s)' % (nextToken.getId(), nextToken) ) + return currentToken + def parse_step_body(self): + current = self.tokens.current() + rule = self.table[0][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(18, self.nonterminals[18])) + tree.list = False + if current == None: + return tree + if rule == 3: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse__gen8() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_workflow(self): + current = self.tokens.current() + rule = self.table[1][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(19, self.nonterminals[19])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 41: + tree.astTransform = AstTransformNodeCreator('Workflow', {'body': 3, 'name': 1}) + t = self.expect(4) # workflow + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(12) # lbrace + tree.add(t) + subtree = self.parse_workflow_body() + tree.add( subtree ) + t = self.expect(9) # rbrace + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_step(self): + current = self.tokens.current() + rule = self.table[2][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(20, self.nonterminals[20])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 40: + tree.astTransform = AstTransformNodeCreator('Step', {'body': 6, 'name': 1, 'parameters': 3}) + t = self.expect(11) # step + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(14) # lparen + tree.add(t) + subtree = self.parse__gen6() + tree.add( subtree ) + t = self.expect(17) # rparen + tree.add(t) + t = self.expect(12) # lbrace + tree.add(t) + subtree = self.parse_step_body() + tree.add( subtree ) + t = self.expect(9) # rbrace + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_step_body_spec(self): + current = self.tokens.current() + rule = self.table[3][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(21, self.nonterminals[21])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 7: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_action() + tree.add( subtree ) + return tree + elif rule == 17: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_output() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse__gen2(self): + current = self.tokens.current() + rule = self.table[4][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(22, self.nonterminals[22])) + tree.list = 'slist' + if current != None and (current.getId() in [17, 10]): + return tree + if current == None: + return tree + if rule == 6: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_workflow_step_input_param() + tree.add( subtree ) + subtree = self.parse__gen3() + tree.add( subtree ) + return tree + return tree + def parse__gen4(self): + current = self.tokens.current() + rule = self.table[5][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(23, self.nonterminals[23])) + tree.list = 'slist' + if current != None and (current.getId() in [17]): + return tree + if current == None: + return tree + if rule == 1: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_workflow_step_output_param() + tree.add( subtree ) + subtree = self.parse__gen5() + tree.add( subtree ) + return tree + return tree + def parse_step_action_sub(self): + current = self.tokens.current() + rule = self.table[6][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(24, self.nonterminals[24])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 29: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_action_command() + tree.add( subtree ) + return tree + elif rule == 42: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_action_scatter_gather() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_step_action_scatter_gather(self): + current = self.tokens.current() + rule = self.table[7][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(25, self.nonterminals[25])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 36: + tree.astTransform = AstTransformNodeCreator('ScatterGatherAction', {'gather': 6, 'scatter': 4, 'prepare': 2}) + t = self.expect(2) # scatter_gather + tree.add(t) + t = self.expect(14) # lparen + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(0) # comma + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(0) # comma + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(17) # rparen + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_step_parameter_type(self): + current = self.tokens.current() + rule = self.table[8][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(26, self.nonterminals[26])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 18: + tree.astTransform = AstTransformSubstitution(0) + t = self.expect(3) # string + tree.add(t) + return tree + elif rule == 27: + tree.astTransform = AstTransformSubstitution(0) + t = self.expect(5) # file + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse__gen6(self): + current = self.tokens.current() + rule = self.table[9][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(27, self.nonterminals[27])) + tree.list = 'slist' + if current != None and (current.getId() in [17]): + return tree + if current == None: + return tree + if rule == 32: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_parameter() + tree.add( subtree ) + subtree = self.parse__gen7() + tree.add( subtree ) + return tree + return tree + def parse__gen5(self): + current = self.tokens.current() + rule = self.table[10][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(28, self.nonterminals[28])) + tree.list = 'slist' + if current != None and (current.getId() in [17]): + return tree + if current == None: + return tree + if rule == 33: + tree.astTransform = AstTransformSubstitution(0) + t = self.expect(0) # comma + tree.add(t) + tree.listSeparator = t + subtree = self.parse_workflow_step_output_param() + tree.add( subtree ) + subtree = self.parse__gen5() + tree.add( subtree ) + return tree + return tree + def parse__gen3(self): + current = self.tokens.current() + rule = self.table[11][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(29, self.nonterminals[29])) + tree.list = 'slist' + if current != None and (current.getId() in [17, 10]): + return tree + if current == None: + return tree + if rule == 9: + tree.astTransform = AstTransformSubstitution(0) + t = self.expect(0) # comma + tree.add(t) + tree.listSeparator = t + subtree = self.parse_workflow_step_input_param() + tree.add( subtree ) + subtree = self.parse__gen3() + tree.add( subtree ) + return tree + return tree + def parse__gen7(self): + current = self.tokens.current() + rule = self.table[12][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(30, self.nonterminals[30])) + tree.list = 'slist' + if current != None and (current.getId() in [17]): + return tree + if current == None: + return tree + if rule == 35: + tree.astTransform = AstTransformSubstitution(0) + t = self.expect(0) # comma + tree.add(t) + tree.listSeparator = t + subtree = self.parse_step_parameter() + tree.add( subtree ) + subtree = self.parse__gen7() + tree.add( subtree ) + return tree + return tree + def parse_step_action_command(self): + current = self.tokens.current() + rule = self.table[13][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(31, self.nonterminals[31])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 5: + tree.astTransform = AstTransformNodeCreator('CommandAction', {'cmd': 2}) + t = self.expect(15) # command + tree.add(t) + t = self.expect(14) # lparen + tree.add(t) + t = self.expect(1) # string_literal + tree.add(t) + t = self.expect(17) # rparen + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse__gen8(self): + current = self.tokens.current() + rule = self.table[14][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(32, self.nonterminals[32])) + tree.list = 'nlist' + if current != None and (current.getId() in [9]): + return tree + if current == None: + return tree + if rule == 24: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step_body_spec() + tree.add( subtree ) + subtree = self.parse__gen8() + tree.add( subtree ) + return tree + return tree + def parse_workflow_body(self): + current = self.tokens.current() + rule = self.table[15][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(33, self.nonterminals[33])) + tree.list = False + if current == None: + return tree + if rule == 31: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse__gen1() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse__gen0(self): + current = self.tokens.current() + rule = self.table[16][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(34, self.nonterminals[34])) + tree.list = 'nlist' + if current != None and (current.getId() in [-1]): + return tree + if current == None: + return tree + if rule == 23: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_wdl_entity() + tree.add( subtree ) + subtree = self.parse__gen0() + tree.add( subtree ) + return tree + return tree + def parse_workflow_step_output(self): + current = self.tokens.current() + rule = self.table[17][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(35, self.nonterminals[35])) + tree.list = False + if current != None and (current.getId() in [6]): + return tree + if current == None: + return tree + if rule == 11: + tree.astTransform = AstTransformSubstitution(1) + t = self.expect(14) # lparen + tree.add(t) + subtree = self.parse__gen4() + tree.add( subtree ) + t = self.expect(17) # rparen + tree.add(t) + t = self.expect(13) # equals + tree.add(t) + return tree + return tree + def parse_step_parameter(self): + current = self.tokens.current() + rule = self.table[18][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(36, self.nonterminals[36])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 12: + tree.astTransform = AstTransformNodeCreator('StepInputParameter', {'type': 2, 'name': 0}) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(8) # colon + tree.add(t) + subtree = self.parse_step_parameter_type() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_workflow_step_input(self): + current = self.tokens.current() + rule = self.table[19][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(37, self.nonterminals[37])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 14: + tree.astTransform = AstTransformSubstitution(1) + t = self.expect(14) # lparen + tree.add(t) + subtree = self.parse__gen2() + tree.add( subtree ) + t = self.expect(17) # rparen + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_wdl(self): + current = self.tokens.current() + rule = self.table[20][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(38, self.nonterminals[38])) + tree.list = False + if current == None: + return tree + if rule == 34: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse__gen0() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_workflow_step_input_param(self): + current = self.tokens.current() + rule = self.table[21][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(39, self.nonterminals[39])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 4: + tree.astTransform = AstTransformNodeCreator('String', {'val': 0}) + t = self.expect(1) # string_literal + tree.add(t) + return tree + elif rule == 15: + tree.astTransform = AstTransformNodeCreator('Variable', {'name': 0}) + t = self.expect(6) # identifier + tree.add(t) + return tree + elif rule == 38: + tree.astTransform = AstTransformNodeCreator('File', {'path': 2}) + t = self.expect(5) # file + tree.add(t) + t = self.expect(14) # lparen + tree.add(t) + t = self.expect(1) # string_literal + tree.add(t) + t = self.expect(17) # rparen + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_workflow_step_output_param(self): + current = self.tokens.current() + rule = self.table[22][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(40, self.nonterminals[40])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 26: + tree.astTransform = AstTransformNodeCreator('Output', {'var': 0}) + t = self.expect(6) # identifier + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_workflow_step(self): + current = self.tokens.current() + rule = self.table[23][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(41, self.nonterminals[41])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 8: + tree.astTransform = AstTransformNodeCreator('WorkflowStep', {'input': 5, 'step': 4, 'name': 1, 'output': 3}) + t = self.expect(11) # step + tree.add(t) + t = self.expect(6) # identifier + tree.add(t) + t = self.expect(8) # colon + tree.add(t) + subtree = self.parse_workflow_step_output() + tree.add( subtree ) + t = self.expect(6) # identifier + tree.add(t) + subtree = self.parse_workflow_step_input() + tree.add( subtree ) + t = self.expect(10) # semi + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse__gen1(self): + current = self.tokens.current() + rule = self.table[24][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(42, self.nonterminals[42])) + tree.list = 'nlist' + if current != None and (current.getId() in [9]): + return tree + if current == None: + return tree + if rule == 2: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_workflow_step() + tree.add( subtree ) + subtree = self.parse__gen1() + tree.add( subtree ) + return tree + return tree + def parse_step_action(self): + current = self.tokens.current() + rule = self.table[25][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(43, self.nonterminals[43])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 30: + tree.astTransform = AstTransformSubstitution(2) + t = self.expect(16) # action + tree.add(t) + t = self.expect(8) # colon + tree.add(t) + subtree = self.parse_step_action_sub() + tree.add( subtree ) + t = self.expect(10) # semi + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_wdl_entity(self): + current = self.tokens.current() + rule = self.table[26][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(44, self.nonterminals[44])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 0: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_step() + tree.add( subtree ) + return tree + elif rule == 16: + tree.astTransform = AstTransformSubstitution(0) + subtree = self.parse_workflow() + tree.add( subtree ) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) + def parse_step_output(self): + current = self.tokens.current() + rule = self.table[27][current.getId()] if current else -1 + tree = ParseTree( NonTerminal(45, self.nonterminals[45])) + tree.list = False + if current == None: + raise SyntaxError('Error: unexpected end of file') + if rule == 19: + tree.astTransform = AstTransformNodeCreator('StepOutputParameters', {'parameters': 2}) + t = self.expect(7) # output + tree.add(t) + t = self.expect(8) # colon + tree.add(t) + subtree = self.parse__gen2() + tree.add( subtree ) + t = self.expect(10) # semi + tree.add(t) + return tree + raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) From 802ef6440f729eb49ca3c300224164d00c35cbe3 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 23:11:00 -0400 Subject: [PATCH 005/140] concept java lexer --- grammars/Lexer.java | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 grammars/Lexer.java diff --git a/grammars/Lexer.java b/grammars/Lexer.java new file mode 100644 index 0000000..df120c1 --- /dev/null +++ b/grammars/Lexer.java @@ -0,0 +1,168 @@ +import java.util.regex.*; +import java.util.ArrayList; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.nio.*; +import java.nio.charset.*; +import java.nio.channels.*; + +class SourceCode { + private File source; + private String resource; + private String contents; + + SourceCode(String source, String resource) { + this.contents = source; + this.resource = resource; + } + + SourceCode(File source) throws IOException { + this(source, "utf-8", source.getCanonicalPath()); + } + + SourceCode(File source, String resource) throws IOException { + this(source, "utf-8", resource); + } + + SourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { + FileChannel channel = new FileInputStream(source).getChannel(); + MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); + Charset cs = Charset.forName(encoding); + CharsetDecoder cd = cs.newDecoder(); + CharBuffer cb = cd.decode(buffer); + this.contents = cb.toString(); + } + + public void advance(int amount) { + this.contents = this.contents.substring(amount); + } + + public String getString() { + return this.contents; + } +} + +class LexerMatch { + private Terminal terminal; + LexerMatch() { this.terminal = null; } + LexerMatch(Terminal terminal) { this.terminal = terminal; } + public Terminal getTerminal() { return this.terminal; } +} + +class TokenLexer { + private Pattern regex; + private WdlParser.TerminalId terminal; + + private String base64_encode(byte[] bytes) { + int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4; + int cycle = 0, b64_index = 0; + byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); + byte[] b64 = new byte[b64_len]; + byte[] buffer = new byte[3]; + Arrays.fill(buffer, (byte) -1); + + for (byte b : bytes) { + int index = cycle % 3; + buffer[index] = b; + boolean last = (cycle == (bytes.length - 1)); + if ( index == 2 || last ) { + if ( last ) { + if ( buffer[1] == -1 ) buffer[1] = 0; + if ( buffer[2] == -1 ) buffer[2] = 0; + } + + b64[b64_index++] = alphabet[buffer[0] >> 2]; + b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)]; + b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)]; + b64[b64_index++] = alphabet[buffer[2] & 0x3f]; + + if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '='; + if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '='; + + Arrays.fill(buffer, (byte) -1); + } + cycle++; + } + return new String(b64); + } + + TokenLexer(Pattern regex, WdlParser.TerminalId terminal) { + this.regex = regex; + this.terminal = terminal; + } + + LexerMatch match(SourceCode source) { + Matcher m = this.regex.matcher(source.getString()); + if ( m.find() ) { + String sourceString = m.group(); + source.advance(sourceString.length()); + + if (this.terminal != null) + return new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), base64_encode(sourceString.getBytes()), "file", 0, 0)); + else + return new LexerMatch(); + } + return null; + } +} + +public class Lexer { + public static void main(String[] args) { + ArrayList regex = new ArrayList(); + regex.add( new TokenLexer(Pattern.compile("^scatter-gather(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_SCATTER_GATHER) ); + regex.add( new TokenLexer(Pattern.compile("^String(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STRING) ); + regex.add( new TokenLexer(Pattern.compile("^workflow(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_WORKFLOW) ); + regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); + regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_OUTPUT) ); + regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STEP) ); + regex.add( new TokenLexer(Pattern.compile("^command(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMMAND) ); + regex.add( new TokenLexer(Pattern.compile("^action(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_ACTION) ); + regex.add( new TokenLexer(Pattern.compile("^,"), WdlParser.TerminalId.TERMINAL_COMMA) ); + regex.add( new TokenLexer(Pattern.compile("^:"), WdlParser.TerminalId.TERMINAL_COLON) ); + regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); + regex.add( new TokenLexer(Pattern.compile("^;"), WdlParser.TerminalId.TERMINAL_SEMI) ); + regex.add( new TokenLexer(Pattern.compile("^\\{"), WdlParser.TerminalId.TERMINAL_LBRACE) ); + regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_EQUALS) ); + regex.add( new TokenLexer(Pattern.compile("^\\("), WdlParser.TerminalId.TERMINAL_LPAREN) ); + regex.add( new TokenLexer(Pattern.compile("^\\)"), WdlParser.TerminalId.TERMINAL_RPAREN) ); + regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING_LITERAL) ); + regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), WdlParser.TerminalId.TERMINAL_IDENTIFIER) ); + regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); + + if ( args.length < 1 ) { + System.err.println("Usage: Lexer "); + System.exit(-1); + } + + try { + SourceCode code = new SourceCode(new File(args[0])); + ArrayList terminal_strings = new ArrayList(); + boolean progress = true; + + while (progress) { + progress = false; + for ( TokenLexer lexer : regex ) { + LexerMatch match = lexer.match(code); + if (match != null) { + progress = true; + if (match.getTerminal() != null) { + terminal_strings.add( " " + match.getTerminal() ); + } + break; + } + } + } + + System.out.println("["); + System.out.println( Utility.join(terminal_strings, ",\n") ); + System.out.println("]"); + System.out.flush(); + } catch (IOException e) { + System.err.println(e); + System.exit(-1); + } + } +} From 966dc66b2817a1ae47414292d764e8d5a4c56719 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 23:11:26 -0400 Subject: [PATCH 006/140] Hermes generated Java parser + dependencies --- grammars/Ast.java | 46 + grammars/AstList.java | 20 + grammars/AstNode.java | 5 + grammars/AstTransform.java | 1 + grammars/AstTransformNodeCreator.java | 24 + grammars/AstTransformSubstitution.java | 12 + grammars/ExpressionParser.java | 3 + grammars/NonTerminal.java | 17 + grammars/ParseTree.java | 159 +++ grammars/ParseTreeNode.java | 6 + grammars/Parser.java | 4 + grammars/ParserMain.java | 75 ++ grammars/SyntaxError.java | 5 + grammars/Terminal.java | 51 + grammars/TerminalMap.java | 6 + grammars/TokenStream.java | 44 + grammars/Utility.java | 23 + grammars/WdlParser.java | 899 +++++++++++++++++ grammars/org/json/CDL.java | 279 ++++++ grammars/org/json/Cookie.java | 169 ++++ grammars/org/json/CookieList.java | 90 ++ grammars/org/json/HTTP.java | 163 ++++ grammars/org/json/HTTPTokener.java | 77 ++ grammars/org/json/JSONArray.class | Bin 0 -> 9162 bytes grammars/org/json/JSONArray.java | 906 ++++++++++++++++++ grammars/org/json/JSONException.class | Bin 0 -> 587 bytes grammars/org/json/JSONException.java | 28 + grammars/org/json/JSONML.java | 467 +++++++++ grammars/org/json/JSONObject$1.class | Bin 0 -> 199 bytes grammars/org/json/JSONObject$Null.class | Bin 0 -> 656 bytes grammars/org/json/JSONObject.class | Bin 0 -> 17385 bytes grammars/org/json/JSONObject.java | 1593 +++++++++++++++++++++++++++++++ grammars/org/json/JSONString.class | Bin 0 -> 156 bytes grammars/org/json/JSONString.java | 18 + grammars/org/json/JSONStringer.java | 78 ++ grammars/org/json/JSONTokener.class | Bin 0 -> 5033 bytes grammars/org/json/JSONTokener.java | 446 +++++++++ grammars/org/json/JSONWriter.java | 327 +++++++ grammars/org/json/XML.java | 508 ++++++++++ grammars/org/json/XMLTokener.java | 365 +++++++ 40 files changed, 6914 insertions(+) create mode 100644 grammars/Ast.java create mode 100644 grammars/AstList.java create mode 100644 grammars/AstNode.java create mode 100644 grammars/AstTransform.java create mode 100644 grammars/AstTransformNodeCreator.java create mode 100644 grammars/AstTransformSubstitution.java create mode 100644 grammars/ExpressionParser.java create mode 100644 grammars/NonTerminal.java create mode 100644 grammars/ParseTree.java create mode 100644 grammars/ParseTreeNode.java create mode 100644 grammars/Parser.java create mode 100644 grammars/ParserMain.java create mode 100644 grammars/SyntaxError.java create mode 100644 grammars/Terminal.java create mode 100644 grammars/TerminalMap.java create mode 100644 grammars/TokenStream.java create mode 100644 grammars/Utility.java create mode 100644 grammars/WdlParser.java create mode 100755 grammars/org/json/CDL.java create mode 100755 grammars/org/json/Cookie.java create mode 100755 grammars/org/json/CookieList.java create mode 100755 grammars/org/json/HTTP.java create mode 100755 grammars/org/json/HTTPTokener.java create mode 100644 grammars/org/json/JSONArray.class create mode 100644 grammars/org/json/JSONArray.java create mode 100644 grammars/org/json/JSONException.class create mode 100755 grammars/org/json/JSONException.java create mode 100755 grammars/org/json/JSONML.java create mode 100644 grammars/org/json/JSONObject$1.class create mode 100644 grammars/org/json/JSONObject$Null.class create mode 100644 grammars/org/json/JSONObject.class create mode 100755 grammars/org/json/JSONObject.java create mode 100644 grammars/org/json/JSONString.class create mode 100755 grammars/org/json/JSONString.java create mode 100755 grammars/org/json/JSONStringer.java create mode 100644 grammars/org/json/JSONTokener.class create mode 100644 grammars/org/json/JSONTokener.java create mode 100755 grammars/org/json/JSONWriter.java create mode 100755 grammars/org/json/XML.java create mode 100755 grammars/org/json/XMLTokener.java diff --git a/grammars/Ast.java b/grammars/Ast.java new file mode 100644 index 0000000..7b020df --- /dev/null +++ b/grammars/Ast.java @@ -0,0 +1,46 @@ +import java.util.Map; +import java.util.LinkedList; +import java.util.Formatter; +import java.util.Locale; +import java.util.ArrayList; +class Ast implements AstNode { + private String name; + private Map attributes; + Ast(String name, Map attributes) { + this.name = name; + this.attributes = attributes; + } + public AstNode getAttribute(String name) { + return this.attributes.get(name); + } + public Map getAttributes() { + return this.attributes; + } + public String getName() { + return this.name; + } + public String toString() { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + LinkedList attributes = new LinkedList(); + for (final Map.Entry attribute : this.attributes.entrySet()) { + final String name = attribute.getKey(); + final AstNode node = attribute.getValue(); + final String nodeStr = (node == null) ? "None" : node.toString(); + attributes.add(name + "=" + nodeStr); + } + formatter.format("(%s: %s)", this.name, Utility.join(attributes, ", ")); + return formatter.toString(); + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + ArrayList children = new ArrayList(); + for( Map.Entry attribute : this.attributes.entrySet() ) { + String valueString = attribute.getValue() == null ? "None" : attribute.getValue().toPrettyString(indent + 2).trim(); + children.add(spaces + " " + attribute.getKey() + "=" + valueString); + } + return spaces + "(" + this.name + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; + } +} diff --git a/grammars/AstList.java b/grammars/AstList.java new file mode 100644 index 0000000..220d2e1 --- /dev/null +++ b/grammars/AstList.java @@ -0,0 +1,20 @@ +import java.util.ArrayList; +class AstList extends ArrayList implements AstNode { + public String toString() { + return "[" + Utility.join(this, ", ") + "]"; + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + if (this.size() == 0) { + return spaces + "[]"; + } + ArrayList elements = new ArrayList(); + for ( AstNode node : this ) { + elements.add(node.toPrettyString(indent + 2)); + } + return spaces + "[\n" + Utility.join(elements, ",\n") + "\n" + spaces + "]"; + } +} diff --git a/grammars/AstNode.java b/grammars/AstNode.java new file mode 100644 index 0000000..5e30462 --- /dev/null +++ b/grammars/AstNode.java @@ -0,0 +1,5 @@ +interface AstNode { + public String toString(); + public String toPrettyString(); + public String toPrettyString(int indent); +} diff --git a/grammars/AstTransform.java b/grammars/AstTransform.java new file mode 100644 index 0000000..f01ae0c --- /dev/null +++ b/grammars/AstTransform.java @@ -0,0 +1 @@ +interface AstTransform {} diff --git a/grammars/AstTransformNodeCreator.java b/grammars/AstTransformNodeCreator.java new file mode 100644 index 0000000..f708c21 --- /dev/null +++ b/grammars/AstTransformNodeCreator.java @@ -0,0 +1,24 @@ +import java.util.LinkedList; +import java.util.Map; +import java.util.LinkedHashMap; +class AstTransformNodeCreator implements AstTransform { + private String name; + private LinkedHashMap parameters; + AstTransformNodeCreator(String name, LinkedHashMap parameters) { + this.name = name; + this.parameters = parameters; + } + public Map getParameters() { + return this.parameters; + } + public String getName() { + return this.name; + } + public String toString() { + LinkedList items = new LinkedList(); + for (final Map.Entry entry : this.parameters.entrySet()) { + items.add(entry.getKey() + "=$" + entry.getValue().toString()); + } + return "AstNodeCreator: " + this.name + "( " + Utility.join(items, ", ") + " )"; + } +} diff --git a/grammars/AstTransformSubstitution.java b/grammars/AstTransformSubstitution.java new file mode 100644 index 0000000..404b7bd --- /dev/null +++ b/grammars/AstTransformSubstitution.java @@ -0,0 +1,12 @@ +class AstTransformSubstitution implements AstTransform { + private int index; + AstTransformSubstitution(int index) { + this.index = index; + } + public int getIndex() { + return this.index; + } + public String toString() { + return "AstSubstitution: $" + Integer.toString(this.index); + } +} diff --git a/grammars/ExpressionParser.java b/grammars/ExpressionParser.java new file mode 100644 index 0000000..7dfbd91 --- /dev/null +++ b/grammars/ExpressionParser.java @@ -0,0 +1,3 @@ +interface ExpressionParser extends Parser { + ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; +} diff --git a/grammars/NonTerminal.java b/grammars/NonTerminal.java new file mode 100644 index 0000000..b0b17e2 --- /dev/null +++ b/grammars/NonTerminal.java @@ -0,0 +1,17 @@ +class NonTerminal { + private int id; + private String string; + NonTerminal(int id, String string) { + this.id = id; + this.string = string; + } + public int getId() { + return this.id; + } + public String getString() { + return this.string; + } + public String toString() { + return this.string; + } +} diff --git a/grammars/ParseTree.java b/grammars/ParseTree.java new file mode 100644 index 0000000..b7a7bda --- /dev/null +++ b/grammars/ParseTree.java @@ -0,0 +1,159 @@ +import java.util.ArrayList; +import java.util.Map; +import java.util.List; +import java.util.LinkedHashMap; +class ParseTree implements ParseTreeNode { + private NonTerminal nonterminal; + private ArrayList children; + private boolean isExpr, isNud, isPrefix, isInfix, isExprNud; + private int nudMorphemeCount; + private Terminal listSeparator; + private String list; + private AstTransform astTransform; + ParseTree(NonTerminal nonterminal) { + this.nonterminal = nonterminal; + this.children = new ArrayList(); + this.astTransform = null; + this.isExpr = false; + this.isNud = false; + this.isPrefix = false; + this.isInfix = false; + this.isExprNud = false; + this.nudMorphemeCount = 0; + this.listSeparator = null; + this.list = ""; + } + public void setExpr(boolean value) { this.isExpr = value; } + public void setNud(boolean value) { this.isNud = value; } + public void setPrefix(boolean value) { this.isPrefix = value; } + public void setInfix(boolean value) { this.isInfix = value; } + public void setExprNud(boolean value) { this.isExprNud = value; } + public void setAstTransformation(AstTransform value) { this.astTransform = value; } + public void setNudMorphemeCount(int value) { this.nudMorphemeCount = value; } + public void setList(String value) { this.list = value; } + public void setListSeparator(Terminal value) { this.listSeparator = value; } + public int getNudMorphemeCount() { return this.nudMorphemeCount; } + public List getChildren() { return this.children; } + public boolean isInfix() { return this.isInfix; } + public boolean isPrefix() { return this.isPrefix; } + public boolean isExpr() { return this.isExpr; } + public boolean isNud() { return this.isNud; } + public boolean isExprNud() { return this.isExprNud; } + public void add(ParseTreeNode tree) { + if (this.children == null) { + this.children = new ArrayList(); + } + this.children.add(tree); + } + private boolean isCompoundNud() { + if ( this.children.size() > 0 && this.children.get(0) instanceof ParseTree ) { + ParseTree child = (ParseTree) this.children.get(0); + if ( child.isNud() && !child.isPrefix() && !this.isExprNud() && !this.isInfix() ) { + return true; + } + } + return false; + } + public AstNode toAst() { + if ( this.list == "slist" || this.list == "nlist" ) { + int offset = (this.children.size() > 0 && this.children.get(0) == this.listSeparator) ? 1 : 0; + AstList astList = new AstList(); + if ( this.children.size() == 0 ) { + return astList; + } + astList.add(this.children.get(offset).toAst()); + astList.addAll((AstList) this.children.get(offset + 1).toAst()); + return astList; + } else if ( this.list == "tlist" ) { + AstList astList = new AstList(); + if ( this.children.size() == 0 ) { + return astList; + } + astList.add(this.children.get(0).toAst()); + astList.addAll((AstList) this.children.get(2).toAst()); + return astList; + } else if ( this.list == "mlist" ) { + AstList astList = new AstList(); + int lastElement = this.children.size() - 1; + if ( this.children.size() == 0 ) { + return astList; + } + for (int i = 0; i < lastElement; i++) { + astList.add(this.children.get(i).toAst()); + } + astList.addAll((AstList) this.children.get(this.children.size() - 1).toAst()); + return astList; + } else if ( this.isExpr ) { + if ( this.astTransform instanceof AstTransformSubstitution ) { + AstTransformSubstitution astSubstitution = (AstTransformSubstitution) astTransform; + return this.children.get(astSubstitution.getIndex()).toAst(); + } else if ( this.astTransform instanceof AstTransformNodeCreator ) { + AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) this.astTransform; + LinkedHashMap parameters = new LinkedHashMap(); + ParseTreeNode child; + for ( final Map.Entry parameter : astNodeCreator.getParameters().entrySet() ) { + String name = parameter.getKey(); + int index = parameter.getValue().intValue(); + if ( index == '$' ) { + child = this.children.get(0); + } else if ( this.isCompoundNud() ) { + ParseTree firstChild = (ParseTree) this.children.get(0); + if ( index < firstChild.getNudMorphemeCount() ) { + child = firstChild.getChildren().get(index); + } else { + index = index - firstChild.getNudMorphemeCount() + 1; + child = this.children.get(index); + } + } else if ( this.children.size() == 1 && !(this.children.get(0) instanceof ParseTree) && !(this.children.get(0) instanceof List) ) { + // TODO: I don't think this should ever be called + child = this.children.get(0); + } else { + child = this.children.get(index); + } + parameters.put(name, child.toAst()); + } + return new Ast(astNodeCreator.getName(), parameters); + } + } else { + AstTransformSubstitution defaultAction = new AstTransformSubstitution(0); + AstTransform action = this.astTransform != null ? this.astTransform : defaultAction; + if (this.children.size() == 0) return null; + if (action instanceof AstTransformSubstitution) { + AstTransformSubstitution astSubstitution = (AstTransformSubstitution) action; + return this.children.get(astSubstitution.getIndex()).toAst(); + } else if (action instanceof AstTransformNodeCreator) { + AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) action; + LinkedHashMap evaluatedParameters = new LinkedHashMap(); + for ( Map.Entry baseParameter : astNodeCreator.getParameters().entrySet() ) { + String name = baseParameter.getKey(); + int index2 = baseParameter.getValue().intValue(); + evaluatedParameters.put(name, this.children.get(index2).toAst()); + } + return new Ast(astNodeCreator.getName(), evaluatedParameters); + } + } + return null; + } + public String toString() { + ArrayList children = new ArrayList(); + for (ParseTreeNode child : this.children) { + children.add(child.toString()); + } + return "(" + this.nonterminal.getString() + ": " + Utility.join(children, ", ") + ")"; + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + if (this.children.size() == 0) { + return "(" + this.nonterminal.toString() + ": )"; + } + String spaces = Utility.getIndentString(indent); + ArrayList children = new ArrayList(); + for ( ParseTreeNode node : this.children ) { + String sub = node.toPrettyString(indent + 2).trim(); + children.add(spaces + " " + sub); + } + return spaces + "(" + this.nonterminal.toString() + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; + } +} diff --git a/grammars/ParseTreeNode.java b/grammars/ParseTreeNode.java new file mode 100644 index 0000000..9d6eb97 --- /dev/null +++ b/grammars/ParseTreeNode.java @@ -0,0 +1,6 @@ +public interface ParseTreeNode { + public AstNode toAst(); + public String toString(); + public String toPrettyString(); + public String toPrettyString(int indent); +} diff --git a/grammars/Parser.java b/grammars/Parser.java new file mode 100644 index 0000000..8746412 --- /dev/null +++ b/grammars/Parser.java @@ -0,0 +1,4 @@ +interface Parser { + ParseTree parse(TokenStream tokens) throws SyntaxError; + TerminalMap getTerminalMap(); +} diff --git a/grammars/ParserMain.java b/grammars/ParserMain.java new file mode 100644 index 0000000..0161c32 --- /dev/null +++ b/grammars/ParserMain.java @@ -0,0 +1,75 @@ +import org.json.*; +import java.io.*; +import java.nio.*; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +class ParserMain { + private static String readStdin() throws IOException { + InputStreamReader stream = new InputStreamReader(System.in, "utf-8"); + char buffer[] = new char[System.in.available()]; + try { + stream.read(buffer, 0, System.in.available()); + } finally { + stream.close(); + } + return new String(buffer); + } + private static String readFile(String path) throws IOException { + FileInputStream stream = new FileInputStream(new File(path)); + try { + FileChannel fc = stream.getChannel(); + MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + /* Instead of using default, pass in a decoder. */ + return Charset.defaultCharset().decode(bb).toString(); + } + finally { + stream.close(); + } + } + private static Parser getParser(String name) throws Exception { + if (name.equals("wdl")) { + return new WdlParser(); + } + throw new Exception("Invalid grammar name: " + name); + } + public static void main(String args[]) { + final String grammars = "wdl"; + if ( args.length < 2 ) { + System.out.println("Usage: ParserMain <" + grammars + "> "); + System.exit(-1); + } + final String grammar = args[0].toLowerCase(); + try { + Parser parser = getParser(grammar); + TerminalMap terminals = parser.getTerminalMap(); + TokenStream tokens = new TokenStream(terminals); + String contents = readStdin(); + JSONArray arr = new JSONArray(contents); + for ( int i = 0; i < arr.length(); i++ ) { + JSONObject token = arr.getJSONObject(i); + tokens.add(new Terminal( + terminals.get(token.getString("terminal")), + token.getString("terminal"), + token.getString("source_string"), + token.getString("resource"), + token.getInt("line"), + token.getInt("col") + )); + } + ParseTreeNode parsetree = parser.parse(tokens); + if ( args.length > 1 && args[1].equals("ast") ) { + AstNode ast = parsetree.toAst(); + if ( ast != null ) { + System.out.println(ast.toPrettyString()); + } else { + System.out.println("None"); + } + } else { + System.out.println(parsetree.toPrettyString()); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + System.exit(-1); + } + } +} diff --git a/grammars/SyntaxError.java b/grammars/SyntaxError.java new file mode 100644 index 0000000..9ea950e --- /dev/null +++ b/grammars/SyntaxError.java @@ -0,0 +1,5 @@ +class SyntaxError extends Exception { + SyntaxError(String message) { + super(message); + } +} diff --git a/grammars/Terminal.java b/grammars/Terminal.java new file mode 100644 index 0000000..ab54dab --- /dev/null +++ b/grammars/Terminal.java @@ -0,0 +1,51 @@ +import java.util.Formatter; +import java.util.Locale; +class Terminal implements AstNode, ParseTreeNode +{ + private int id; + private String terminal_str; + private String base64_source_string; + private String resource; + private int line; + private int col; + Terminal(int id, String terminal_str, String base64_source_string, String resource, int line, int col) { + this.id = id; + this.terminal_str = terminal_str; + this.base64_source_string = base64_source_string; + this.resource = resource; + this.line = line; + this.col = col; + } + public int getId() { + return this.id; + } + public String getTerminalStr() { + return this.terminal_str; + } + public String getBase64SourceString() { + return this.base64_source_string; + } + public String getResource() { + return this.resource; + } + public int getLine() { + return this.line; + } + public int getColumn() { + return this.col; + } + public String toString() { + StringBuilder sb = new StringBuilder(); + Formatter formatter = new Formatter(sb, Locale.US); + formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), this.getBase64SourceString()); + return formatter.toString(); + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + return spaces + this.getTerminalStr(); + } + public AstNode toAst() { return this; } +} diff --git a/grammars/TerminalMap.java b/grammars/TerminalMap.java new file mode 100644 index 0000000..f198d39 --- /dev/null +++ b/grammars/TerminalMap.java @@ -0,0 +1,6 @@ +interface TerminalMap { + int get(String string); + String get(int id); + boolean isValid(String string); + boolean isValid(int id); +} diff --git a/grammars/TokenStream.java b/grammars/TokenStream.java new file mode 100644 index 0000000..b50e557 --- /dev/null +++ b/grammars/TokenStream.java @@ -0,0 +1,44 @@ +import java.util.ArrayList; +import java.util.Formatter; +import java.util.Locale; +class TokenStream extends ArrayList { + private int index; + private TerminalMap terminals; + TokenStream(TerminalMap terminals) { + this.terminals = terminals; + reset(); + } + public void reset() { + this.index = 0; + } + public Terminal advance() { + this.index += 1; + return this.current(); + } + public Terminal current() { + try { + return this.get(this.index); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + public Terminal expect(int expecting) throws SyntaxError { + Terminal current = current(); + if (current == null) { + throw new SyntaxError( "No more tokens. Expecting " + this.terminals.get(expecting) ); + } + if (current.getId() != expecting) { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); + throw new SyntaxError(formatter.toString()); + } + Terminal next = advance(); + if ( next != null && !this.terminals.isValid(next.getId()) ) { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + formatter.format("Invalid symbol ID: %d (%s)", next.getId(), next.getTerminalStr()); + throw new SyntaxError(formatter.toString()); + } + return current; + } +} diff --git a/grammars/Utility.java b/grammars/Utility.java new file mode 100644 index 0000000..576a77e --- /dev/null +++ b/grammars/Utility.java @@ -0,0 +1,23 @@ +import java.util.Collection; +import java.util.Iterator; +class Utility { + public static String join(Collection s, String delimiter) { + StringBuilder builder = new StringBuilder(); + Iterator iter = s.iterator(); + while (iter.hasNext()) { + builder.append(iter.next()); + if (!iter.hasNext()) { + break; + } + builder.append(delimiter); + } + return builder.toString(); + } + public static String getIndentString(int spaces) { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < spaces; i++) { + sb.append(' '); + } + return sb.toString(); + } +} diff --git a/grammars/WdlParser.java b/grammars/WdlParser.java new file mode 100644 index 0000000..5dc0eaa --- /dev/null +++ b/grammars/WdlParser.java @@ -0,0 +1,899 @@ + +import java.util.*; +import java.util.HashMap; +import java.util.LinkedHashMap; +class WdlParser implements Parser { + private TokenStream tokens; + private HashMap expressionParsers; + /* table[nonterminal][terminal] = rule */ + private static final int[][] table = { + { -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 35, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 21, -1, -1 }, + { 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1 }, + { 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 25, -1, -1, -1, -1, 25, -1, 25, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 16, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, + { 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1 }, + { -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, 40, -1 }, + { -1, -1, -1, -1, -1, 26, 26, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1 }, + { 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 31, 36, 36, -1, -1, -1, -1, 31, -1, -1, -1, -1, 31, -1 }, + { -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 7, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, 33, -1 }, + { -1, -1, -1, 11, -1, -1, -1, -1, 17, -1, 17, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1 }, + }; + public enum TerminalId { + TERMINAL_STEP(0, "step"), + TERMINAL_COLON(1, "colon"), + TERMINAL_LBRACE(2, "lbrace"), + TERMINAL_RBRACE(3, "rbrace"), + TERMINAL_STRING_LITERAL(4, "string_literal"), + TERMINAL_RPAREN(5, "rparen"), + TERMINAL_SEMI(6, "semi"), + TERMINAL_COMMAND(7, "command"), + TERMINAL_OUTPUT(8, "output"), + TERMINAL_SCATTER_GATHER(9, "scatter_gather"), + TERMINAL_ACTION(10, "action"), + TERMINAL_IDENTIFIER(11, "identifier"), + TERMINAL_COMMA(12, "comma"), + TERMINAL_STRING(13, "string"), + TERMINAL_WORKFLOW(14, "workflow"), + TERMINAL_LPAREN(15, "lparen"), + TERMINAL_FILE(16, "file"), + TERMINAL_EQUALS(17, "equals"); + private final int id; + private final String string; + TerminalId(int id, String string) { + this.id = id; + this.string = string; + } + public int id() {return id;} + public String string() {return string;} + } + private class WdlTerminalMap implements TerminalMap { + private Map id_to_str; + private Map str_to_id; + WdlTerminalMap(TerminalId[] terminals) { + id_to_str = new HashMap(); + str_to_id = new HashMap(); + for( TerminalId terminal : terminals ) { + Integer id = new Integer(terminal.id()); + String str = terminal.string(); + id_to_str.put(id, str); + str_to_id.put(str, id); + } + } + public int get(String string) { return this.str_to_id.get(string); } + public String get(int id) { return this.id_to_str.get(id); } + public boolean isValid(String string) { return this.str_to_id.containsKey(string); } + public boolean isValid(int id) { return this.id_to_str.containsKey(id); } + } + WdlParser() { + this.expressionParsers = new HashMap(); + } + public TerminalMap getTerminalMap() { + return new WdlTerminalMap(TerminalId.values()); + } + public ParseTree parse(TokenStream tokens) throws SyntaxError { + this.tokens = tokens; + ParseTree tree = this.parse_wdl(); + if (this.tokens.current() != null) { + throw new SyntaxError("Finished parsing without consuming all tokens."); + } + return tree; + } + private boolean isTerminal(TerminalId terminal) { + return (0 <= terminal.id() && terminal.id() <= 17); + } + private boolean isNonTerminal(TerminalId terminal) { + return (18 <= terminal.id() && terminal.id() <= 45); + } + private boolean isTerminal(int terminal) { + return (0 <= terminal && terminal <= 17); + } + private boolean isNonTerminal(int terminal) { + return (18 <= terminal && terminal <= 45); + } + private ParseTree parse_step_action_command() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[0][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(18, "step_action_command")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 12) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("cmd", 2); + tree.setAstTransformation(new AstTransformNodeCreator("CommandAction", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMAND.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow_body() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(19, "workflow_body")); + tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen1(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen1() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(20, "_gen1")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 3) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 35) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_workflow_step(); + tree.add( subtree); + subtree = this.parse__gen1(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_wdl_entity() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(21, "wdl_entity")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 5) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_workflow(); + tree.add( subtree); + return tree; + } + else if (rule == 37) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow_step_output() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(22, "workflow_step_output")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 11) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 21) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + subtree = this.parse__gen4(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_EQUALS.id()); + tree.add(next); + return tree; + } + return tree; + } + private ParseTree parse_wdl() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "wdl")); + tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 41) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_action() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "step_action")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 27) { + tree.setAstTransformation(new AstTransformSubstitution(2)); + next = this.tokens.expect(TerminalId.TERMINAL_ACTION.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse_step_action_sub(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow_step() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "workflow_step")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 42) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("input", 5); + parameters.put("step", 4); + parameters.put("name", 1); + parameters.put("output", 3); + tree.setAstTransformation(new AstTransformNodeCreator("WorkflowStep", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse_workflow_step_output(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse_workflow_step_input(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow_step_input() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "workflow_step_input")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_action_scatter_gather() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "step_action_scatter_gather")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 24) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("gather", 6); + parameters.put("scatter", 4); + parameters.put("prepare", 2); + tree.setAstTransformation(new AstTransformNodeCreator("ScatterGatherAction", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_SCATTER_GATHER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_body() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "step_body")); + tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 25) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen8(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "workflow")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 30) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Workflow", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_WORKFLOW.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse_workflow_body(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_workflow_step_output_param() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "workflow_step_output_param")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 15) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("var", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Output", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_output() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "step_output")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameters", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputParameters", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_body_spec() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "step_body_spec")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output(); + tree.add( subtree); + return tree; + } + else if (rule == 16) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_action(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen5() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "_gen5")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 13) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_workflow_step_output_param(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen0() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "_gen0")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == -1) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 39) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_wdl_entity(); + tree.add( subtree); + subtree = this.parse__gen0(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_workflow_step_input_param() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "workflow_step_input_param")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 19) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + else if (rule == 34) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("val", 0); + tree.setAstTransformation(new AstTransformNodeCreator("String", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); + tree.add(next); + return tree; + } + else if (rule == 40) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("path", 2); + tree.setAstTransformation(new AstTransformNodeCreator("File", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen3() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "_gen3")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 6 || current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 23) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_workflow_step_input_param(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_step() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "step")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 18) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 6); + parameters.put("name", 1); + parameters.put("parameters", 3); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + subtree = this.parse__gen6(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse_step_body(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen2() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen2")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 6 || current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_workflow_step_input_param(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen4() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen4")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 14) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_workflow_step_output_param(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_step_action_sub() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "step_action_sub")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 7) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_action_command(); + tree.add( subtree); + return tree; + } + else if (rule == 29) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_action_scatter_gather(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_parameter_type() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "step_parameter_type")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 22) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); + tree.add(next); + return tree; + } + else if (rule == 33) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen8() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "_gen8")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 3) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 17) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_body_spec(); + tree.add( subtree); + subtree = this.parse__gen8(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen6() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen6")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 3) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_parameter(); + tree.add( subtree); + subtree = this.parse__gen7(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen7() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "_gen7")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 5) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 4) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_parameter(); + tree.add( subtree); + subtree = this.parse__gen7(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_step_parameter() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "step_parameter")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 9) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("type", 2); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputParameter", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse_step_parameter_type(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } +} diff --git a/grammars/org/json/CDL.java b/grammars/org/json/CDL.java new file mode 100755 index 0000000..fd5d476 --- /dev/null +++ b/grammars/org/json/CDL.java @@ -0,0 +1,279 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * This provides static methods to convert comma delimited text into a + * JSONArray, and to covert a JSONArray into comma delimited text. Comma + * delimited text is a very popular format for data interchange. It is + * understood by most database, spreadsheet, and organizer programs. + *

+ * Each row of text represents a row in a table or a data record. Each row + * ends with a NEWLINE character. Each row contains one or more values. + * Values are separated by commas. A value can contain any character except + * for comma, unless is is wrapped in single quotes or double quotes. + *

+ * The first row usually contains the names of the columns. + *

+ * A comma delimited list can be converted into a JSONArray of JSONObjects. + * The names for the elements in the JSONObjects can be taken from the names + * in the first row. + * @author JSON.org + * @version 2010-12-24 + */ +public class CDL { + + /** + * Get the next value. The value can be wrapped in quotes. The value can + * be empty. + * @param x A JSONTokener of the source text. + * @return The value string, or null if empty. + * @throws JSONException if the quoted string is badly formed. + */ + private static String getValue(JSONTokener x) throws JSONException { + char c; + char q; + StringBuffer sb; + do { + c = x.next(); + } while (c == ' ' || c == '\t'); + switch (c) { + case 0: + return null; + case '"': + case '\'': + q = c; + sb = new StringBuffer(); + for (;;) { + c = x.next(); + if (c == q) { + break; + } + if (c == 0 || c == '\n' || c == '\r') { + throw x.syntaxError("Missing close quote '" + q + "'."); + } + sb.append(c); + } + return sb.toString(); + case ',': + x.back(); + return ""; + default: + x.back(); + return x.nextTo(','); + } + } + + /** + * Produce a JSONArray of strings from a row of comma delimited values. + * @param x A JSONTokener of the source text. + * @return A JSONArray of strings. + * @throws JSONException + */ + public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { + JSONArray ja = new JSONArray(); + for (;;) { + String value = getValue(x); + char c = x.next(); + if (value == null || + (ja.length() == 0 && value.length() == 0 && c != ',')) { + return null; + } + ja.put(value); + for (;;) { + if (c == ',') { + break; + } + if (c != ' ') { + if (c == '\n' || c == '\r' || c == 0) { + return ja; + } + throw x.syntaxError("Bad character '" + c + "' (" + + (int)c + ")."); + } + c = x.next(); + } + } + } + + /** + * Produce a JSONObject from a row of comma delimited text, using a + * parallel JSONArray of strings to provides the names of the elements. + * @param names A JSONArray of names. This is commonly obtained from the + * first row of a comma delimited text file using the rowToJSONArray + * method. + * @param x A JSONTokener of the source text. + * @return A JSONObject combining the names and values. + * @throws JSONException + */ + public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) + throws JSONException { + JSONArray ja = rowToJSONArray(x); + return ja != null ? ja.toJSONObject(names) : null; + } + + /** + * Produce a comma delimited text row from a JSONArray. Values containing + * the comma character will be quoted. Troublesome characters may be + * removed. + * @param ja A JSONArray of strings. + * @return A string ending in NEWLINE. + */ + public static String rowToString(JSONArray ja) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < ja.length(); i += 1) { + if (i > 0) { + sb.append(','); + } + Object object = ja.opt(i); + if (object != null) { + String string = object.toString(); + if (string.length() > 0 && (string.indexOf(',') >= 0 || + string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || + string.indexOf(0) >= 0 || string.charAt(0) == '"')) { + sb.append('"'); + int length = string.length(); + for (int j = 0; j < length; j += 1) { + char c = string.charAt(j); + if (c >= ' ' && c != '"') { + sb.append(c); + } + } + sb.append('"'); + } else { + sb.append(string); + } + } + } + sb.append('\n'); + return sb.toString(); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return toJSONArray(new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param x The JSONTokener containing the comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONTokener x) throws JSONException { + return toJSONArray(rowToJSONArray(x), x); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONArray names, String string) + throws JSONException { + return toJSONArray(names, new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param x A JSONTokener of the source text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONArray names, JSONTokener x) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (;;) { + JSONObject jo = rowToJSONObject(names, x); + if (jo == null) { + break; + } + ja.put(jo); + } + if (ja.length() == 0) { + return null; + } + return ja; + } + + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects. The + * first row will be a list of names obtained by inspecting the first + * JSONObject. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException + */ + public static String toString(JSONArray ja) throws JSONException { + JSONObject jo = ja.optJSONObject(0); + if (jo != null) { + JSONArray names = jo.names(); + if (names != null) { + return rowToString(names) + toString(names, ja); + } + } + return null; + } + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects using + * a provided list of names. The list of names is not included in the + * output. + * @param names A JSONArray of strings. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException + */ + public static String toString(JSONArray names, JSONArray ja) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < ja.length(); i += 1) { + JSONObject jo = ja.optJSONObject(i); + if (jo != null) { + sb.append(rowToString(jo.toJSONArray(names))); + } + } + return sb.toString(); + } +} diff --git a/grammars/org/json/Cookie.java b/grammars/org/json/Cookie.java new file mode 100755 index 0000000..9cf5ce2 --- /dev/null +++ b/grammars/org/json/Cookie.java @@ -0,0 +1,169 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Convert a web browser cookie specification to a JSONObject and back. + * JSON and Cookies are both notations for name/value pairs. + * @author JSON.org + * @version 2010-12-24 + */ +public class Cookie { + + /** + * Produce a copy of a string in which the characters '+', '%', '=', ';' + * and control characters are replaced with "%hh". This is a gentle form + * of URL encoding, attempting to cause as little distortion to the + * string as possible. The characters '=' and ';' are meta characters in + * cookies. By convention, they are escaped using the URL-encoding. This is + * only a convention, not a standard. Often, cookies are expected to have + * encoded values. We encode '=' and ';' because we must. We encode '%' and + * '+' because they are meta characters in URL encoding. + * @param string The source string. + * @return The escaped result. + */ + public static String escape(String string) { + char c; + String s = string.trim(); + StringBuffer sb = new StringBuffer(); + int length = s.length(); + for (int i = 0; i < length; i += 1) { + c = s.charAt(i); + if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { + sb.append('%'); + sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); + sb.append(Character.forDigit((char)(c & 0x0f), 16)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + + /** + * Convert a cookie specification string into a JSONObject. The string + * will contain a name value pair separated by '='. The name and the value + * will be unescaped, possibly converting '+' and '%' sequences. The + * cookie properties may follow, separated by ';', also represented as + * name=value (except the secure property, which does not have a value). + * The name will be stored under the key "name", and the value will be + * stored under the key "value". This method does not do checking or + * validation of the parameters. It only converts the cookie string into + * a JSONObject. + * @param string The cookie specification string. + * @return A JSONObject containing "name", "value", and possibly other + * members. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + String name; + JSONObject jo = new JSONObject(); + Object value; + JSONTokener x = new JSONTokener(string); + jo.put("name", x.nextTo('=')); + x.next('='); + jo.put("value", x.nextTo(';')); + x.next(); + while (x.more()) { + name = unescape(x.nextTo("=;")); + if (x.next() != '=') { + if (name.equals("secure")) { + value = Boolean.TRUE; + } else { + throw x.syntaxError("Missing '=' in cookie parameter."); + } + } else { + value = unescape(x.nextTo(';')); + x.next(); + } + jo.put(name, value); + } + return jo; + } + + + /** + * Convert a JSONObject into a cookie specification string. The JSONObject + * must contain "name" and "value" members. + * If the JSONObject contains "expires", "domain", "path", or "secure" + * members, they will be appended to the cookie specification string. + * All other members are ignored. + * @param jo A JSONObject + * @return A cookie specification string + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuffer sb = new StringBuffer(); + + sb.append(escape(jo.getString("name"))); + sb.append("="); + sb.append(escape(jo.getString("value"))); + if (jo.has("expires")) { + sb.append(";expires="); + sb.append(jo.getString("expires")); + } + if (jo.has("domain")) { + sb.append(";domain="); + sb.append(escape(jo.getString("domain"))); + } + if (jo.has("path")) { + sb.append(";path="); + sb.append(escape(jo.getString("path"))); + } + if (jo.optBoolean("secure")) { + sb.append(";secure"); + } + return sb.toString(); + } + + /** + * Convert %hh sequences to single characters, and + * convert plus to space. + * @param string A string that may contain + * + (plus) and + * %hh sequences. + * @return The unescaped string. + */ + public static String unescape(String string) { + int length = string.length(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; ++i) { + char c = string.charAt(i); + if (c == '+') { + c = ' '; + } else if (c == '%' && i + 2 < length) { + int d = JSONTokener.dehexchar(string.charAt(i + 1)); + int e = JSONTokener.dehexchar(string.charAt(i + 2)); + if (d >= 0 && e >= 0) { + c = (char)(d * 16 + e); + i += 2; + } + } + sb.append(c); + } + return sb.toString(); + } +} diff --git a/grammars/org/json/CookieList.java b/grammars/org/json/CookieList.java new file mode 100755 index 0000000..7f4fe07 --- /dev/null +++ b/grammars/org/json/CookieList.java @@ -0,0 +1,90 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + +/** + * Convert a web browser cookie list string to a JSONObject and back. + * @author JSON.org + * @version 2010-12-24 + */ +public class CookieList { + + /** + * Convert a cookie list into a JSONObject. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The names and the values + * will be unescaped, possibly converting '+' and '%' sequences. + * + * To add a cookie to a cooklist, + * cookielistJSONObject.put(cookieJSONObject.getString("name"), + * cookieJSONObject.getString("value")); + * @param string A cookie list string + * @return A JSONObject + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + JSONTokener x = new JSONTokener(string); + while (x.more()) { + String name = Cookie.unescape(x.nextTo('=')); + x.next('='); + jo.put(name, Cookie.unescape(x.nextTo(';'))); + x.next(); + } + return jo; + } + + + /** + * Convert a JSONObject into a cookie list. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The characters '%', '+', '=', and ';' + * in the names and values are replaced by "%hh". + * @param jo A JSONObject + * @return A cookie list string + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + boolean b = false; + Iterator keys = jo.keys(); + String string; + StringBuffer sb = new StringBuffer(); + while (keys.hasNext()) { + string = keys.next().toString(); + if (!jo.isNull(string)) { + if (b) { + sb.append(';'); + } + sb.append(Cookie.escape(string)); + sb.append("="); + sb.append(Cookie.escape(jo.getString(string))); + b = true; + } + } + return sb.toString(); + } +} diff --git a/grammars/org/json/HTTP.java b/grammars/org/json/HTTP.java new file mode 100755 index 0000000..43d04a8 --- /dev/null +++ b/grammars/org/json/HTTP.java @@ -0,0 +1,163 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + +/** + * Convert an HTTP header to a JSONObject and back. + * @author JSON.org + * @version 2010-12-24 + */ +public class HTTP { + + /** Carriage return/line feed. */ + public static final String CRLF = "\r\n"; + + /** + * Convert an HTTP header string into a JSONObject. It can be a request + * header or a response header. A request header will contain + *

{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header will contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * In addition, the other parameters in the header will be captured, using + * the HTTP field names as JSON names, so that
+     *    Date: Sun, 26 May 2002 18:06:04 GMT
+     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
+     *    Cache-Control: no-cache
+ * become + *
{...
+     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
+     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
+     *    "Cache-Control": "no-cache",
+     * ...}
+ * It does no further checking or conversion. It does not parse dates. + * It does not do '%' transforms on URLs. + * @param string An HTTP header string. + * @return A JSONObject containing the elements and attributes + * of the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + HTTPTokener x = new HTTPTokener(string); + String token; + + token = x.nextToken(); + if (token.toUpperCase().startsWith("HTTP")) { + +// Response + + jo.put("HTTP-Version", token); + jo.put("Status-Code", x.nextToken()); + jo.put("Reason-Phrase", x.nextTo('\0')); + x.next(); + + } else { + +// Request + + jo.put("Method", token); + jo.put("Request-URI", x.nextToken()); + jo.put("HTTP-Version", x.nextToken()); + } + +// Fields + + while (x.more()) { + String name = x.nextTo(':'); + x.next(':'); + jo.put(name, x.nextTo('\0')); + x.next(); + } + return jo; + } + + + /** + * Convert a JSONObject into an HTTP header. A request header must contain + *
{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header must contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * Any other members of the JSONObject will be output as HTTP fields. + * The result will end with two CRLF pairs. + * @param jo A JSONObject + * @return An HTTP header string. + * @throws JSONException if the object does not contain enough + * information. + */ + public static String toString(JSONObject jo) throws JSONException { + Iterator keys = jo.keys(); + String string; + StringBuffer sb = new StringBuffer(); + if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { + sb.append(jo.getString("HTTP-Version")); + sb.append(' '); + sb.append(jo.getString("Status-Code")); + sb.append(' '); + sb.append(jo.getString("Reason-Phrase")); + } else if (jo.has("Method") && jo.has("Request-URI")) { + sb.append(jo.getString("Method")); + sb.append(' '); + sb.append('"'); + sb.append(jo.getString("Request-URI")); + sb.append('"'); + sb.append(' '); + sb.append(jo.getString("HTTP-Version")); + } else { + throw new JSONException("Not enough material for an HTTP header."); + } + sb.append(CRLF); + while (keys.hasNext()) { + string = keys.next().toString(); + if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && + !"Reason-Phrase".equals(string) && !"Method".equals(string) && + !"Request-URI".equals(string) && !jo.isNull(string)) { + sb.append(string); + sb.append(": "); + sb.append(jo.getString(string)); + sb.append(CRLF); + } + } + sb.append(CRLF); + return sb.toString(); + } +} diff --git a/grammars/org/json/HTTPTokener.java b/grammars/org/json/HTTPTokener.java new file mode 100755 index 0000000..f62b3d5 --- /dev/null +++ b/grammars/org/json/HTTPTokener.java @@ -0,0 +1,77 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The HTTPTokener extends the JSONTokener to provide additional methods + * for the parsing of HTTP headers. + * @author JSON.org + * @version 2010-12-24 + */ +public class HTTPTokener extends JSONTokener { + + /** + * Construct an HTTPTokener from a string. + * @param string A source string. + */ + public HTTPTokener(String string) { + super(string); + } + + + /** + * Get the next token or string. This is used in parsing HTTP headers. + * @throws JSONException + * @return A String. + */ + public String nextToken() throws JSONException { + char c; + char q; + StringBuffer sb = new StringBuffer(); + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == '"' || c == '\'') { + q = c; + for (;;) { + c = next(); + if (c < ' ') { + throw syntaxError("Unterminated string."); + } + if (c == q) { + return sb.toString(); + } + sb.append(c); + } + } + for (;;) { + if (c == 0 || Character.isWhitespace(c)) { + return sb.toString(); + } + sb.append(c); + c = next(); + } + } +} diff --git a/grammars/org/json/JSONArray.class b/grammars/org/json/JSONArray.class new file mode 100644 index 0000000000000000000000000000000000000000..83e6c9969cb05b848d6436f3b238b1765f0e822e GIT binary patch literal 9162 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 ze%xssget and opt + * methods for accessing the values by index, and put methods for + * adding or replacing values. The values can be any of these types: + * Boolean, JSONArray, JSONObject, + * Number, String, or the + * JSONObject.NULL object. + *

+ * The constructor can convert a JSON text into a Java object. The + * toString method converts to JSON text. + *

+ * A get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. + *

+ * The texts produced by the toString methods strictly conform to + * JSON syntax rules. The constructors are more forgiving in the texts they will + * accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing bracket.
  • + *
  • The null value will be inserted when there is , + *  (comma) elision.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , = ; # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
  • Values can be separated by ; (semicolon) as + * well as by , (comma).
  • + *
+ * + * @author JSON.org + * @version 2012-04-20 + */ +public class JSONArray { + + + /** + * The arrayList where the JSONArray's properties are kept. + */ + private final ArrayList myArrayList; + + + /** + * Construct an empty JSONArray. + */ + public JSONArray() { + this.myArrayList = new ArrayList(); + } + + /** + * Construct a JSONArray from a JSONTokener. + * @param x A JSONTokener + * @throws JSONException If there is a syntax error. + */ + public JSONArray(JSONTokener x) throws JSONException { + this(); + if (x.nextClean() != '[') { + throw x.syntaxError("A JSONArray text must start with '['"); + } + if (x.nextClean() != ']') { + x.back(); + for (;;) { + if (x.nextClean() == ',') { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } else { + x.back(); + this.myArrayList.add(x.nextValue()); + } + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == ']') { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); + } + } + } + } + + + /** + * Construct a JSONArray from a source JSON text. + * @param source A string that begins with + * [ (left bracket) + * and ends with ] (right bracket). + * @throws JSONException If there is a syntax error. + */ + public JSONArray(String source) throws JSONException { + this(new JSONTokener(source)); + } + + + /** + * Construct a JSONArray from a Collection. + * @param collection A Collection. + */ + public JSONArray(Collection collection) { + this.myArrayList = new ArrayList(); + if (collection != null) { + Iterator iter = collection.iterator(); + while (iter.hasNext()) { + this.myArrayList.add(JSONObject.wrap(iter.next())); + } + } + } + + + /** + * Construct a JSONArray from an array + * @throws JSONException If not an array. + */ + public JSONArray(Object array) throws JSONException { + this(); + if (array.getClass().isArray()) { + int length = Array.getLength(array); + for (int i = 0; i < length; i += 1) { + this.put(JSONObject.wrap(Array.get(array, i))); + } + } else { + throw new JSONException( +"JSONArray initial value should be a string or collection or array."); + } + } + + + /** + * Get the object value associated with an index. + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException If there is no value for the index. + */ + public Object get(int index) throws JSONException { + Object object = this.opt(index); + if (object == null) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + + /** + * Get the boolean value associated with an index. + * The string values "true" and "false" are converted to boolean. + * + * @param index The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException If there is no value for the index or if the + * value is not convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONArray[" + index + "] is not a boolean."); + } + + + /** + * Get the double value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value cannot + * be converted to a number. + */ + public double getDouble(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the int value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the JSONArray associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException If there is no value for the index. or if the + * value is not a JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONArray) { + return (JSONArray)object; + } + throw new JSONException("JSONArray[" + index + + "] is not a JSONArray."); + } + + + /** + * Get the JSONObject associated with an index. + * @param index subscript + * @return A JSONObject value. + * @throws JSONException If there is no value for the index or if the + * value is not a JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONObject) { + return (JSONObject)object; + } + throw new JSONException("JSONArray[" + index + + "] is not a JSONObject."); + } + + + /** + * Get the long value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value cannot + * be converted to a number. + */ + public long getLong(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the string associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException If there is no string value for the index. + */ + public String getString(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof String) { + return (String)object; + } + throw new JSONException("JSONArray[" + index + "] not a string."); + } + + + /** + * Determine if the value is null. + * @param index The index must be between 0 and length() - 1. + * @return true if the value at the index is null, or if there is no value. + */ + public boolean isNull(int index) { + return JSONObject.NULL.equals(this.opt(index)); + } + + + /** + * Make a string from the contents of this JSONArray. The + * separator string is inserted between each element. + * Warning: This method assumes that the data structure is acyclical. + * @param separator A string that will be inserted between the elements. + * @return a string. + * @throws JSONException If the array contains an invalid number. + */ + public String join(String separator) throws JSONException { + int len = this.length(); + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < len; i += 1) { + if (i > 0) { + sb.append(separator); + } + sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + } + return sb.toString(); + } + + + /** + * Get the number of elements in the JSONArray, included nulls. + * + * @return The length (or size). + */ + public int length() { + return this.myArrayList.size(); + } + + + /** + * Get the optional object value associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return An object value, or null if there is no + * object at that index. + */ + public Object opt(int index) { + return (index < 0 || index >= this.length()) + ? null + : this.myArrayList.get(index); + } + + + /** + * Get the optional boolean value associated with an index. + * It returns false if there is no value at that index, + * or if the value is not Boolean.TRUE or the String "true". + * + * @param index The index must be between 0 and length() - 1. + * @return The truth. + */ + public boolean optBoolean(int index) { + return this.optBoolean(index, false); + } + + + /** + * Get the optional boolean value associated with an index. + * It returns the defaultValue if there is no value at that index or if + * it is not a Boolean or the String "true" or "false" (case insensitive). + * + * @param index The index must be between 0 and length() - 1. + * @param defaultValue A boolean default. + * @return The truth. + */ + public boolean optBoolean(int index, boolean defaultValue) { + try { + return this.getBoolean(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional double value associated with an index. + * NaN is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public double optDouble(int index) { + return this.optDouble(index, Double.NaN); + } + + + /** + * Get the optional double value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index subscript + * @param defaultValue The default value. + * @return The value. + */ + public double optDouble(int index, double defaultValue) { + try { + return this.getDouble(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional int value associated with an index. + * Zero is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public int optInt(int index) { + return this.optInt(index, 0); + } + + + /** + * Get the optional int value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return The value. + */ + public int optInt(int index, int defaultValue) { + try { + return this.getInt(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional JSONArray associated with an index. + * @param index subscript + * @return A JSONArray value, or null if the index has no value, + * or if the value is not a JSONArray. + */ + public JSONArray optJSONArray(int index) { + Object o = this.opt(index); + return o instanceof JSONArray ? (JSONArray)o : null; + } + + + /** + * Get the optional JSONObject associated with an index. + * Null is returned if the key is not found, or null if the index has + * no value, or if the value is not a JSONObject. + * + * @param index The index must be between 0 and length() - 1. + * @return A JSONObject value. + */ + public JSONObject optJSONObject(int index) { + Object o = this.opt(index); + return o instanceof JSONObject ? (JSONObject)o : null; + } + + + /** + * Get the optional long value associated with an index. + * Zero is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public long optLong(int index) { + return this.optLong(index, 0); + } + + + /** + * Get the optional long value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return The value. + */ + public long optLong(int index, long defaultValue) { + try { + return this.getLong(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional string value associated with an index. It returns an + * empty string if there is no value at that index. If the value + * is not a string and is not null, then it is coverted to a string. + * + * @param index The index must be between 0 and length() - 1. + * @return A String value. + */ + public String optString(int index) { + return this.optString(index, ""); + } + + + /** + * Get the optional string associated with an index. + * The defaultValue is returned if the key is not found. + * + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return A String value. + */ + public String optString(int index, String defaultValue) { + Object object = this.opt(index); + return JSONObject.NULL.equals(object) + ? defaultValue : object + .toString(); + } + + + /** + * Append a boolean value. This increases the array's length by one. + * + * @param value A boolean value. + * @return this. + */ + public JSONArray put(boolean value) { + this.put(value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONArray which is produced from a Collection. + * @param value A Collection value. + * @return this. + */ + public JSONArray put(Collection value) { + this.put(new JSONArray(value)); + return this; + } + + + /** + * Append a double value. This increases the array's length by one. + * + * @param value A double value. + * @throws JSONException if the value is not finite. + * @return this. + */ + public JSONArray put(double value) throws JSONException { + Double d = new Double(value); + JSONObject.testValidity(d); + this.put(d); + return this; + } + + + /** + * Append an int value. This increases the array's length by one. + * + * @param value An int value. + * @return this. + */ + public JSONArray put(int value) { + this.put(new Integer(value)); + return this; + } + + + /** + * Append an long value. This increases the array's length by one. + * + * @param value A long value. + * @return this. + */ + public JSONArray put(long value) { + this.put(new Long(value)); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONObject which is produced from a Map. + * @param value A Map value. + * @return this. + */ + public JSONArray put(Map value) { + this.put(new JSONObject(value)); + return this; + } + + + /** + * Append an object value. This increases the array's length by one. + * @param value An object value. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + */ + public JSONArray put(Object value) { + this.myArrayList.add(value); + return this; + } + + + /** + * Put or replace a boolean value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * @param index The subscript. + * @param value A boolean value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, boolean value) throws JSONException { + this.put(index, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONArray which is produced from a Collection. + * @param index The subscript. + * @param value A Collection value. + * @return this. + * @throws JSONException If the index is negative or if the value is + * not finite. + */ + public JSONArray put(int index, Collection value) throws JSONException { + this.put(index, new JSONArray(value)); + return this; + } + + + /** + * Put or replace a double value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value A double value. + * @return this. + * @throws JSONException If the index is negative or if the value is + * not finite. + */ + public JSONArray put(int index, double value) throws JSONException { + this.put(index, new Double(value)); + return this; + } + + + /** + * Put or replace an int value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value An int value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, int value) throws JSONException { + this.put(index, new Integer(value)); + return this; + } + + + /** + * Put or replace a long value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value A long value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, long value) throws JSONException { + this.put(index, new Long(value)); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONObject that is produced from a Map. + * @param index The subscript. + * @param value The Map value. + * @return this. + * @throws JSONException If the index is negative or if the the value is + * an invalid number. + */ + public JSONArray put(int index, Map value) throws JSONException { + this.put(index, new JSONObject(value)); + return this; + } + + + /** + * Put or replace an object value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * @param index The subscript. + * @param value The value to put into the array. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + * @throws JSONException If the index is negative or if the the value is + * an invalid number. + */ + public JSONArray put(int index, Object value) throws JSONException { + JSONObject.testValidity(value); + if (index < 0) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + if (index < this.length()) { + this.myArrayList.set(index, value); + } else { + while (index != this.length()) { + this.put(JSONObject.NULL); + } + this.put(value); + } + return this; + } + + + /** + * Remove an index and close the hole. + * @param index The index of the element to be removed. + * @return The value that was associated with the index, + * or null if there was no value. + */ + public Object remove(int index) { + Object o = this.opt(index); + this.myArrayList.remove(index); + return o; + } + + + /** + * Produce a JSONObject by combining a JSONArray of names with the values + * of this JSONArray. + * @param names A JSONArray containing a list of key strings. These will be + * paired with the values. + * @return A JSONObject, or null if there are no names or if this JSONArray + * has no values. + * @throws JSONException If any of the names are null. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + if (names == null || names.length() == 0 || this.length() == 0) { + return null; + } + JSONObject jo = new JSONObject(); + for (int i = 0; i < names.length(); i += 1) { + jo.put(names.getString(i), this.opt(i)); + } + return jo; + } + + + /** + * Make a JSON text of this JSONArray. For compactness, no + * unnecessary whitespace is added. If it is not possible to produce a + * syntactically correct JSON text then null will be returned instead. This + * could occur if the array contains an invalid number. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, transmittable + * representation of the array. + */ + public String toString() { + try { + return '[' + this.join(",") + ']'; + } catch (Exception e) { + return null; + } + } + + + /** + * Make a prettyprinted JSON text of this JSONArray. + * Warning: This method assumes that the data structure is acyclical. + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @return a printable, displayable, transmittable + * representation of the object, beginning + * with [ (left bracket) and ending + * with ] (right bracket). + * @throws JSONException + */ + public String toString(int indentFactor) throws JSONException { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + return this.write(sw, indentFactor, 0).toString(); + } + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indention of the top level. + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + int length = this.length(); + writer.write('['); + + if (length == 1) { + JSONObject.writeValue(writer, this.myArrayList.get(0), + indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + + for (int i = 0; i < length; i += 1) { + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, newindent); + JSONObject.writeValue(writer, this.myArrayList.get(i), + indentFactor, newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, indent); + } + writer.write(']'); + return writer; + } catch (IOException e) { + throw new JSONException(e); + } + } +} diff --git a/grammars/org/json/JSONException.class b/grammars/org/json/JSONException.class new file mode 100644 index 0000000000000000000000000000000000000000..61db0afc1768f7283d4f622d95e48f1a1d7d75e9 GIT binary patch literal 587 zcmY*W%TB^T6g^WYm0CdFh_C31M*@jkj2qNMg17+L4>+kMwKaXHpQVY9#DyQ=M;UKx zL!pa1GpFZq@66Bd*EfJ;9H@{{QBg%LjU=`e)D`S7Y`MZQxH%P$YuMJ!NSDW7~J;;=%~b3WM?W z==^yu9y}VW6ZEPfgRFvG4SU$vunCQ!Vmo?w;o4Srjn7bwr(3$Lq03|nrtYqU>vElf zOKbf_bK{V%Jh(&&b)=wxMhZ`9LZ}hiCkUhdsOIQ&M7Tt2s@47kd!-${6je1u^W;?s z`T2<7iTK%8`vVe5TJ3ivVqKQ}fik65D5XlO0*aA#k5)#1<<=V#FUzP@2-c~V2$N9$ E18ksnod5s; literal 0 HcmV?d00001 diff --git a/grammars/org/json/JSONException.java b/grammars/org/json/JSONException.java new file mode 100755 index 0000000..289b602 --- /dev/null +++ b/grammars/org/json/JSONException.java @@ -0,0 +1,28 @@ +package org.json; + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * @author JSON.org + * @version 2010-12-24 + */ +public class JSONException extends Exception { + private static final long serialVersionUID = 0; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * @param message Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + public Throwable getCause() { + return this.cause; + } +} diff --git a/grammars/org/json/JSONML.java b/grammars/org/json/JSONML.java new file mode 100755 index 0000000..f29ee72 --- /dev/null +++ b/grammars/org/json/JSONML.java @@ -0,0 +1,467 @@ +package org.json; + +/* +Copyright (c) 2008 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + + +/** + * This provides static methods to convert an XML text into a JSONArray or + * JSONObject, and to covert a JSONArray or JSONObject into an XML text using + * the JsonML transform. + * + * @author JSON.org + * @version 2012-03-28 + */ +public class JSONML { + + /** + * Parse XML values and store them in a JSONArray. + * @param x The XMLTokener containing the source string. + * @param arrayForm true if array form, false if object form. + * @param ja The JSONArray that is containing the current tag or null + * if we are at the outermost level. + * @return A JSONArray if the value is the outermost tag, otherwise null. + * @throws JSONException + */ + private static Object parse( + XMLTokener x, + boolean arrayForm, + JSONArray ja + ) throws JSONException { + String attribute; + char c; + String closeTag = null; + int i; + JSONArray newja = null; + JSONObject newjo = null; + Object token; + String tagName = null; + +// Test for and skip past these forms: +// +// +// +// + + while (true) { + if (!x.more()) { + throw x.syntaxError("Bad XML"); + } + token = x.nextContent(); + if (token == XML.LT) { + token = x.nextToken(); + if (token instanceof Character) { + if (token == XML.SLASH) { + +// Close tag "); + } else { + x.back(); + } + } else if (c == '[') { + token = x.nextToken(); + if (token.equals("CDATA") && x.next() == '[') { + if (ja != null) { + ja.put(x.nextCDATA()); + } + } else { + throw x.syntaxError("Expected 'CDATA['"); + } + } else { + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + } + } else if (token == XML.QUEST) { + +// "); + } else { + throw x.syntaxError("Misshaped tag"); + } + +// Open tag < + + } else { + if (!(token instanceof String)) { + throw x.syntaxError("Bad tagName '" + token + "'."); + } + tagName = (String)token; + newja = new JSONArray(); + newjo = new JSONObject(); + if (arrayForm) { + newja.put(tagName); + if (ja != null) { + ja.put(newja); + } + } else { + newjo.put("tagName", tagName); + if (ja != null) { + ja.put(newjo); + } + } + token = null; + for (;;) { + if (token == null) { + token = x.nextToken(); + } + if (token == null) { + throw x.syntaxError("Misshaped tag"); + } + if (!(token instanceof String)) { + break; + } + +// attribute = value + + attribute = (String)token; + if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { + throw x.syntaxError("Reserved attribute."); + } + token = x.nextToken(); + if (token == XML.EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + newjo.accumulate(attribute, XML.stringToValue((String)token)); + token = null; + } else { + newjo.accumulate(attribute, ""); + } + } + if (arrayForm && newjo.length() > 0) { + newja.put(newjo); + } + +// Empty tag <.../> + + if (token == XML.SLASH) { + if (x.nextToken() != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } + +// Content, between <...> and + + } else { + if (token != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + closeTag = (String)parse(x, arrayForm, newja); + if (closeTag != null) { + if (!closeTag.equals(tagName)) { + throw x.syntaxError("Mismatched '" + tagName + + "' and '" + closeTag + "'"); + } + tagName = null; + if (!arrayForm && newja.length() > 0) { + newjo.put("childNodes", newja); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } + } + } + } + } else { + if (ja != null) { + ja.put(token instanceof String + ? XML.stringToValue((String)token) + : token); + } + } + } + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child tags. + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param string The source string. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return toJSONArray(new XMLTokener(string)); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child content and tags. + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param x An XMLTokener. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJSONArray(XMLTokener x) throws JSONException { + return (JSONArray)parse(x, true, null); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param x An XMLTokener of the XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(XMLTokener x) throws JSONException { + return (JSONObject)parse(x, false, null); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param string The XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + return toJSONObject(new XMLTokener(string)); + } + + + /** + * Reverse the JSONML transformation, making an XML text from a JSONArray. + * @param ja A JSONArray. + * @return An XML string. + * @throws JSONException + */ + public static String toString(JSONArray ja) throws JSONException { + int i; + JSONObject jo; + String key; + Iterator keys; + int length; + Object object; + StringBuffer sb = new StringBuffer(); + String tagName; + String value; + +// Emit = length) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + do { + object = ja.get(i); + i += 1; + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } + } + } while (i < length); + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } + + /** + * Reverse the JSONML transformation, making an XML text from a JSONObject. + * The JSONObject must contain a "tagName" property. If it has children, + * then it must have a "childNodes" property containing an array of objects. + * The other properties are attributes with string values. + * @param jo A JSONObject. + * @return An XML string. + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuffer sb = new StringBuffer(); + int i; + JSONArray ja; + String key; + Iterator keys; + int length; + Object object; + String tagName; + String value; + +//Emit '); + } else { + sb.append('>'); + length = ja.length(); + for (i = 0; i < length; i += 1) { + object = ja.get(i); + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } else { + sb.append(object.toString()); + } + } + } + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } +} diff --git a/grammars/org/json/JSONObject$1.class b/grammars/org/json/JSONObject$1.class new file mode 100644 index 0000000000000000000000000000000000000000..64c0e8fc984702841f9e103c6212c0616f9c9baa GIT binary patch literal 199 zcmX^0Z`VEs1_mPr9(D$Hb_Om+2Cm@z(xT*4x6GVWMh1SbV1GaVq^#8B61}X%vP7VW zYhH3resN}Ax^HSpMt%xA12-dsXns+;epYdQo<2goiXkHd10w^EXI@@vk#kOBadB!f zBZC0Q6#bmUymWntv5XADSTqYL0JSm!9R>o-K*#{(u`sX#X%+@HAjt{DTtGF9Af5mR E00_A(^Z)<= literal 0 HcmV?d00001 diff --git a/grammars/org/json/JSONObject$Null.class b/grammars/org/json/JSONObject$Null.class new file mode 100644 index 0000000000000000000000000000000000000000..eb7d3742de52026cd9f35e43bb555c3ab6ef82a6 GIT binary patch literal 656 zcmZutJx{_=6g{s6S}IuNL!kJvIPj5(=!h{UBqkb!p~k_jU?s)+s%B?V)vV)m@7Z>fPSZ?uSj1vF}Ef8!+U`^X~x8r%qSbduZ**aZ(-|8VuaJd?CAtf$K`5wF^>v2Fsh&V`%G)CY zi5PnA3u>+U1SRr}i2Nc(|A{|fnJO{JarsaP>qt!nN`%5lPRp}Sk0~*dof1WO;UvPd a`S22QW6xD&2-8GeK@mu)^cO{xVEh6ptae}k literal 0 HcmV?d00001 diff --git a/grammars/org/json/JSONObject.class b/grammars/org/json/JSONObject.class new file mode 100644 index 0000000000000000000000000000000000000000..0393352d40d455cdf8aa5094900778d208c22927 GIT binary patch literal 17385 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 S<|@O7Tmz6K?h{Q;_x}OfJSF%5 literal 0 HcmV?d00001 diff --git a/grammars/org/json/JSONObject.java b/grammars/org/json/JSONObject.java new file mode 100755 index 0000000..ffe5315 --- /dev/null +++ b/grammars/org/json/JSONObject.java @@ -0,0 +1,1593 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * A JSONObject is an unordered collection of name/value pairs. Its external + * form is a string wrapped in curly braces with colons between the names and + * values, and commas between the values and names. The internal form is an + * object having get and opt methods for accessing the + * values by name, and put methods for adding or replacing values + * by name. The values can be any of these types: Boolean, + * JSONArray, JSONObject, Number, + * String, or the JSONObject.NULL object. A JSONObject + * constructor can be used to convert an external form JSON text into an + * internal form whose values can be retrieved with the get and + * opt methods, or to convert values into a JSON text using the + * put and toString methods. A get method + * returns a value if one can be found, and throws an exception if one cannot be + * found. An opt method returns a default value instead of throwing + * an exception, and so is useful for obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object, which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. The opt methods differ from the get methods in that they do + * not throw. Instead, they return a specified value, such as null. + *

+ * The put methods add or replace values in an object. For example, + * + *

+ * myString = new JSONObject().put("JSON", "Hello, World!").toString();
+ * 
+ * + * produces the string {"JSON": "Hello, World"}. + *

+ * The texts produced by the toString methods strictly conform to + * the JSON syntax rules. The constructors are more forgiving in the texts they + * will accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing brace.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , = ; # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
  • Keys can be followed by = or => as well as by + * :.
  • + *
  • Values can be followed by ; (semicolon) as + * well as by , (comma).
  • + *
+ * + * @author JSON.org + * @version 2012-07-02 + */ +public class JSONObject { + + /** + * JSONObject.NULL is equivalent to the value that JavaScript calls null, + * whilst Java's null is equivalent to the value that JavaScript calls + * undefined. + */ + private static final class Null { + + /** + * There is only intended to be a single instance of the NULL object, + * so the clone method returns itself. + * @return NULL. + */ + protected final Object clone() { + return this; + } + + /** + * A Null object is equal to the null value and to itself. + * @param object An object to test for nullness. + * @return true if the object parameter is the JSONObject.NULL object + * or null. + */ + public boolean equals(Object object) { + return object == null || object == this; + } + + /** + * Get the "null" string value. + * @return The string "null". + */ + public String toString() { + return "null"; + } + } + + + /** + * The map where the JSONObject's properties are kept. + */ + private final Map map; + + + /** + * It is sometimes more convenient and less ambiguous to have a + * NULL object than to use Java's null value. + * JSONObject.NULL.equals(null) returns true. + * JSONObject.NULL.toString() returns "null". + */ + public static final Object NULL = new Null(); + + + /** + * Construct an empty JSONObject. + */ + public JSONObject() { + this.map = new HashMap(); + } + + + /** + * Construct a JSONObject from a subset of another JSONObject. + * An array of strings is used to identify the keys that should be copied. + * Missing keys are ignored. + * @param jo A JSONObject. + * @param names An array of strings. + * @throws JSONException + * @exception JSONException If a value is a non-finite number or if a name is duplicated. + */ + public JSONObject(JSONObject jo, String[] names) { + this(); + for (int i = 0; i < names.length; i += 1) { + try { + this.putOnce(names[i], jo.opt(names[i])); + } catch (Exception ignore) { + } + } + } + + + /** + * Construct a JSONObject from a JSONTokener. + * @param x A JSONTokener object containing the source string. + * @throws JSONException If there is a syntax error in the source string + * or a duplicated key. + */ + public JSONObject(JSONTokener x) throws JSONException { + this(); + char c; + String key; + + if (x.nextClean() != '{') { + throw x.syntaxError("A JSONObject text must begin with '{'"); + } + for (;;) { + c = x.nextClean(); + switch (c) { + case 0: + throw x.syntaxError("A JSONObject text must end with '}'"); + case '}': + return; + default: + x.back(); + key = x.nextValue().toString(); + } + +// The key is followed by ':'. We will also tolerate '=' or '=>'. + + c = x.nextClean(); + if (c == '=') { + if (x.next() != '>') { + x.back(); + } + } else if (c != ':') { + throw x.syntaxError("Expected a ':' after a key"); + } + this.putOnce(key, x.nextValue()); + +// Pairs are separated by ','. We will also tolerate ';'. + + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == '}') { + return; + } + x.back(); + break; + case '}': + return; + default: + throw x.syntaxError("Expected a ',' or '}'"); + } + } + } + + + /** + * Construct a JSONObject from a Map. + * + * @param map A map object that can be used to initialize the contents of + * the JSONObject. + * @throws JSONException + */ + public JSONObject(Map map) { + this.map = new HashMap(); + if (map != null) { + Iterator i = map.entrySet().iterator(); + while (i.hasNext()) { + Map.Entry e = (Map.Entry)i.next(); + Object value = e.getValue(); + if (value != null) { + this.map.put(e.getKey(), wrap(value)); + } + } + } + } + + + /** + * Construct a JSONObject from an Object using bean getters. + * It reflects on all of the public methods of the object. + * For each of the methods with no parameters and a name starting + * with "get" or "is" followed by an uppercase letter, + * the method is invoked, and a key and the value returned from the getter method + * are put into the new JSONObject. + * + * The key is formed by removing the "get" or "is" prefix. + * If the second remaining character is not upper case, then the first + * character is converted to lower case. + * + * For example, if an object has a method named "getName", and + * if the result of calling object.getName() is "Larry Fine", + * then the JSONObject will contain "name": "Larry Fine". + * + * @param bean An object that has getter methods that should be used + * to make a JSONObject. + */ + public JSONObject(Object bean) { + this(); + this.populateMap(bean); + } + + + /** + * Construct a JSONObject from an Object, using reflection to find the + * public members. The resulting JSONObject's keys will be the strings + * from the names array, and the values will be the field values associated + * with those keys in the object. If a key is not found or not visible, + * then it will not be copied into the new JSONObject. + * @param object An object that has fields that should be used to make a + * JSONObject. + * @param names An array of strings, the names of the fields to be obtained + * from the object. + */ + public JSONObject(Object object, String names[]) { + this(); + Class c = object.getClass(); + for (int i = 0; i < names.length; i += 1) { + String name = names[i]; + try { + this.putOpt(name, c.getField(name).get(object)); + } catch (Exception ignore) { + } + } + } + + + /** + * Construct a JSONObject from a source JSON text string. + * This is the most commonly used JSONObject constructor. + * @param source A string beginning + * with { (left brace) and ending + * with } (right brace). + * @exception JSONException If there is a syntax error in the source + * string or a duplicated key. + */ + public JSONObject(String source) throws JSONException { + this(new JSONTokener(source)); + } + + + /** + * Construct a JSONObject from a ResourceBundle. + * @param baseName The ResourceBundle base name. + * @param locale The Locale to load the ResourceBundle for. + * @throws JSONException If any JSONExceptions are detected. + */ + public JSONObject(String baseName, Locale locale) throws JSONException { + this(); + ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + Thread.currentThread().getContextClassLoader()); + +// Iterate through the keys in the bundle. + + Enumeration keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + if (key instanceof String) { + +// Go through the path, ensuring that there is a nested JSONObject for each +// segment except the last. Add the value using the last segment's name into +// the deepest nested JSONObject. + + String[] path = ((String)key).split("\\."); + int last = path.length - 1; + JSONObject target = this; + for (int i = 0; i < last; i += 1) { + String segment = path[i]; + JSONObject nextTarget = target.optJSONObject(segment); + if (nextTarget == null) { + nextTarget = new JSONObject(); + target.put(segment, nextTarget); + } + target = nextTarget; + } + target.put(path[last], bundle.getString((String)key)); + } + } + } + + + /** + * Accumulate values under a key. It is similar to the put method except + * that if there is already an object stored under the key then a + * JSONArray is stored under the key to hold all of the accumulated values. + * If there is already a JSONArray, then the new value is appended to it. + * In contrast, the put method replaces the previous value. + * + * If only one value is accumulated that is not a JSONArray, then the + * result will be the same as using put. But if multiple values are + * accumulated, then the result will be like append. + * @param key A key string. + * @param value An object to be accumulated under the key. + * @return this. + * @throws JSONException If the value is an invalid number + * or if the key is null. + */ + public JSONObject accumulate( + String key, + Object value + ) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, value instanceof JSONArray + ? new JSONArray().put(value) + : value); + } else if (object instanceof JSONArray) { + ((JSONArray)object).put(value); + } else { + this.put(key, new JSONArray().put(object).put(value)); + } + return this; + } + + + /** + * Append values to the array under a key. If the key does not exist in the + * JSONObject, then the key is put in the JSONObject with its value being a + * JSONArray containing the value parameter. If the key was already + * associated with a JSONArray, then the value parameter is appended to it. + * @param key A key string. + * @param value An object to be accumulated under the key. + * @return this. + * @throws JSONException If the key is null or if the current value + * associated with the key is not a JSONArray. + */ + public JSONObject append(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, new JSONArray().put(value)); + } else if (object instanceof JSONArray) { + this.put(key, ((JSONArray)object).put(value)); + } else { + throw new JSONException("JSONObject[" + key + + "] is not a JSONArray."); + } + return this; + } + + + /** + * Produce a string from a double. The string "null" will be returned if + * the number is not finite. + * @param d A double. + * @return A String. + */ + public static String doubleToString(double d) { + if (Double.isInfinite(d) || Double.isNaN(d)) { + return "null"; + } + +// Shave off trailing zeros and decimal point, if possible. + + String string = Double.toString(d); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + + /** + * Get the value object associated with a key. + * + * @param key A key string. + * @return The object associated with the key. + * @throws JSONException if the key is not found. + */ + public Object get(String key) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + Object object = this.opt(key); + if (object == null) { + throw new JSONException("JSONObject[" + quote(key) + + "] not found."); + } + return object; + } + + + /** + * Get the boolean value associated with a key. + * + * @param key A key string. + * @return The truth. + * @throws JSONException + * if the value is not a Boolean or the String "true" or "false". + */ + public boolean getBoolean(String key) throws JSONException { + Object object = this.get(key); + if (object.equals(Boolean.FALSE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a Boolean."); + } + + + /** + * Get the double value associated with a key. + * @param key A key string. + * @return The numeric value. + * @throws JSONException if the key is not found or + * if the value is not a Number object and cannot be converted to a number. + */ + public double getDouble(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a number."); + } + } + + + /** + * Get the int value associated with a key. + * + * @param key A key string. + * @return The integer value. + * @throws JSONException if the key is not found or if the value cannot + * be converted to an integer. + */ + public int getInt(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not an int."); + } + } + + + /** + * Get the JSONArray value associated with a key. + * + * @param key A key string. + * @return A JSONArray which is the value. + * @throws JSONException if the key is not found or + * if the value is not a JSONArray. + */ + public JSONArray getJSONArray(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONArray) { + return (JSONArray)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONArray."); + } + + + /** + * Get the JSONObject value associated with a key. + * + * @param key A key string. + * @return A JSONObject which is the value. + * @throws JSONException if the key is not found or + * if the value is not a JSONObject. + */ + public JSONObject getJSONObject(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONObject) { + return (JSONObject)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONObject."); + } + + + /** + * Get the long value associated with a key. + * + * @param key A key string. + * @return The long value. + * @throws JSONException if the key is not found or if the value cannot + * be converted to a long. + */ + public long getLong(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a long."); + } + } + + + /** + * Get an array of field names from a JSONObject. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(JSONObject jo) { + int length = jo.length(); + if (length == 0) { + return null; + } + Iterator iterator = jo.keys(); + String[] names = new String[length]; + int i = 0; + while (iterator.hasNext()) { + names[i] = (String)iterator.next(); + i += 1; + } + return names; + } + + + /** + * Get an array of field names from an Object. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(Object object) { + if (object == null) { + return null; + } + Class klass = object.getClass(); + Field[] fields = klass.getFields(); + int length = fields.length; + if (length == 0) { + return null; + } + String[] names = new String[length]; + for (int i = 0; i < length; i += 1) { + names[i] = fields[i].getName(); + } + return names; + } + + + /** + * Get the string associated with a key. + * + * @param key A key string. + * @return A string which is the value. + * @throws JSONException if there is no string value for the key. + */ + public String getString(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof String) { + return (String)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] not a string."); + } + + + /** + * Determine if the JSONObject contains a specific key. + * @param key A key string. + * @return true if the key exists in the JSONObject. + */ + public boolean has(String key) { + return this.map.containsKey(key); + } + + + /** + * Increment a property of a JSONObject. If there is no such property, + * create one with a value of 1. If there is such a property, and if + * it is an Integer, Long, Double, or Float, then add one to it. + * @param key A key string. + * @return this. + * @throws JSONException If there is already a property with this name + * that is not an Integer, Long, Double, or Float. + */ + public JSONObject increment(String key) throws JSONException { + Object value = this.opt(key); + if (value == null) { + this.put(key, 1); + } else if (value instanceof Integer) { + this.put(key, ((Integer)value).intValue() + 1); + } else if (value instanceof Long) { + this.put(key, ((Long)value).longValue() + 1); + } else if (value instanceof Double) { + this.put(key, ((Double)value).doubleValue() + 1); + } else if (value instanceof Float) { + this.put(key, ((Float)value).floatValue() + 1); + } else { + throw new JSONException("Unable to increment [" + quote(key) + "]."); + } + return this; + } + + + /** + * Determine if the value associated with the key is null or if there is + * no value. + * @param key A key string. + * @return true if there is no value associated with the key or if + * the value is the JSONObject.NULL object. + */ + public boolean isNull(String key) { + return JSONObject.NULL.equals(this.opt(key)); + } + + + /** + * Get an enumeration of the keys of the JSONObject. + * + * @return An iterator of the keys. + */ + public Iterator keys() { + return this.map.keySet().iterator(); + } + + + /** + * Get the number of keys stored in the JSONObject. + * + * @return The number of keys in the JSONObject. + */ + public int length() { + return this.map.size(); + } + + + /** + * Produce a JSONArray containing the names of the elements of this + * JSONObject. + * @return A JSONArray containing the key strings, or null if the JSONObject + * is empty. + */ + public JSONArray names() { + JSONArray ja = new JSONArray(); + Iterator keys = this.keys(); + while (keys.hasNext()) { + ja.put(keys.next()); + } + return ja.length() == 0 ? null : ja; + } + + /** + * Produce a string from a Number. + * @param number A Number + * @return A String. + * @throws JSONException If n is a non-finite number. + */ + public static String numberToString(Number number) + throws JSONException { + if (number == null) { + throw new JSONException("Null pointer"); + } + testValidity(number); + +// Shave off trailing zeros and decimal point, if possible. + + String string = number.toString(); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + + /** + * Get an optional value associated with a key. + * @param key A key string. + * @return An object which is the value, or null if there is no value. + */ + public Object opt(String key) { + return key == null ? null : this.map.get(key); + } + + + /** + * Get an optional boolean associated with a key. + * It returns false if there is no such key, or if the value is not + * Boolean.TRUE or the String "true". + * + * @param key A key string. + * @return The truth. + */ + public boolean optBoolean(String key) { + return this.optBoolean(key, false); + } + + + /** + * Get an optional boolean associated with a key. + * It returns the defaultValue if there is no such key, or if it is not + * a Boolean or the String "true" or "false" (case insensitive). + * + * @param key A key string. + * @param defaultValue The default. + * @return The truth. + */ + public boolean optBoolean(String key, boolean defaultValue) { + try { + return this.getBoolean(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional double associated with a key, + * or NaN if there is no such key or if its value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A string which is the key. + * @return An object which is the value. + */ + public double optDouble(String key) { + return this.optDouble(key, Double.NaN); + } + + + /** + * Get an optional double associated with a key, or the + * defaultValue if there is no such key or if its value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public double optDouble(String key, double defaultValue) { + try { + return this.getDouble(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional int value associated with a key, + * or zero if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @return An object which is the value. + */ + public int optInt(String key) { + return this.optInt(key, 0); + } + + + /** + * Get an optional int value associated with a key, + * or the default if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public int optInt(String key, int defaultValue) { + try { + return this.getInt(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional JSONArray associated with a key. + * It returns null if there is no such key, or if its value is not a + * JSONArray. + * + * @param key A key string. + * @return A JSONArray which is the value. + */ + public JSONArray optJSONArray(String key) { + Object o = this.opt(key); + return o instanceof JSONArray ? (JSONArray)o : null; + } + + + /** + * Get an optional JSONObject associated with a key. + * It returns null if there is no such key, or if its value is not a + * JSONObject. + * + * @param key A key string. + * @return A JSONObject which is the value. + */ + public JSONObject optJSONObject(String key) { + Object object = this.opt(key); + return object instanceof JSONObject ? (JSONObject)object : null; + } + + + /** + * Get an optional long value associated with a key, + * or zero if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @return An object which is the value. + */ + public long optLong(String key) { + return this.optLong(key, 0); + } + + + /** + * Get an optional long value associated with a key, + * or the default if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public long optLong(String key, long defaultValue) { + try { + return this.getLong(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional string associated with a key. + * It returns an empty string if there is no such key. If the value is not + * a string and is not null, then it is converted to a string. + * + * @param key A key string. + * @return A string which is the value. + */ + public String optString(String key) { + return this.optString(key, ""); + } + + + /** + * Get an optional string associated with a key. + * It returns the defaultValue if there is no such key. + * + * @param key A key string. + * @param defaultValue The default. + * @return A string which is the value. + */ + public String optString(String key, String defaultValue) { + Object object = this.opt(key); + return NULL.equals(object) ? defaultValue : object.toString(); + } + + + private void populateMap(Object bean) { + Class klass = bean.getClass(); + +// If klass is a System class then set includeSuperClass to false. + + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass + ? klass.getMethods() + : klass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i += 1) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || + "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && + Character.isUpperCase(key.charAt(0)) && + method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + + key.substring(1); + } + + Object result = method.invoke(bean, (Object[])null); + if (result != null) { + this.map.put(key, wrap(result)); + } + } + } + } catch (Exception ignore) { + } + } + } + + + /** + * Put a key/boolean pair in the JSONObject. + * + * @param key A key string. + * @param value A boolean which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, boolean value) throws JSONException { + this.put(key, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONArray which is produced from a Collection. + * @param key A key string. + * @param value A Collection value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Collection value) throws JSONException { + this.put(key, new JSONArray(value)); + return this; + } + + + /** + * Put a key/double pair in the JSONObject. + * + * @param key A key string. + * @param value A double which is the value. + * @return this. + * @throws JSONException If the key is null or if the number is invalid. + */ + public JSONObject put(String key, double value) throws JSONException { + this.put(key, new Double(value)); + return this; + } + + + /** + * Put a key/int pair in the JSONObject. + * + * @param key A key string. + * @param value An int which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, int value) throws JSONException { + this.put(key, new Integer(value)); + return this; + } + + + /** + * Put a key/long pair in the JSONObject. + * + * @param key A key string. + * @param value A long which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, long value) throws JSONException { + this.put(key, new Long(value)); + return this; + } + + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONObject which is produced from a Map. + * @param key A key string. + * @param value A Map value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Map value) throws JSONException { + this.put(key, new JSONObject(value)); + return this; + } + + + /** + * Put a key/value pair in the JSONObject. If the value is null, + * then the key will be removed from the JSONObject if it is present. + * @param key A key string. + * @param value An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, + * or the JSONObject.NULL object. + * @return this. + * @throws JSONException If the value is non-finite number + * or if the key is null. + */ + public JSONObject put(String key, Object value) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + if (value != null) { + testValidity(value); + this.map.put(key, value); + } else { + this.remove(key); + } + return this; + } + + + /** + * Put a key/value pair in the JSONObject, but only if the key and the + * value are both non-null, and only if there is not already a member + * with that name. + * @param key + * @param value + * @return his. + * @throws JSONException if the key is a duplicate + */ + public JSONObject putOnce(String key, Object value) throws JSONException { + if (key != null && value != null) { + if (this.opt(key) != null) { + throw new JSONException("Duplicate key \"" + key + "\""); + } + this.put(key, value); + } + return this; + } + + + /** + * Put a key/value pair in the JSONObject, but only if the + * key and the value are both non-null. + * @param key A key string. + * @param value An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, + * or the JSONObject.NULL object. + * @return this. + * @throws JSONException If the value is a non-finite number. + */ + public JSONObject putOpt(String key, Object value) throws JSONException { + if (key != null && value != null) { + this.put(key, value); + } + return this; + } + + + /** + * Produce a string in double quotes with backslash sequences in all the + * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') + || (c >= '\u2000' && c < '\u2100')) { + hhhh = "000" + Integer.toHexString(c); + w.write("\\u" + hhhh.substring(hhhh.length() - 4)); + } else { + w.write(c); + } + } + } + w.write('"'); + return w; + } + + /** + * Remove a name and its value, if present. + * @param key The name to be removed. + * @return The value that was associated with the name, + * or null if there was no value. + */ + public Object remove(String key) { + return this.map.remove(key); + } + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. + * @param string A String. + * @return A simple JSON value. + */ + public static Object stringToValue(String string) { + Double d; + if (string.equals("")) { + return string; + } + if (string.equalsIgnoreCase("true")) { + return Boolean.TRUE; + } + if (string.equalsIgnoreCase("false")) { + return Boolean.FALSE; + } + if (string.equalsIgnoreCase("null")) { + return JSONObject.NULL; + } + + /* + * If it might be a number, try converting it. + * If a number cannot be produced, then the value will just + * be a string. Note that the plus and implied string + * conventions are non-standard. A JSON parser may accept + * non-JSON forms as long as it accepts all correct JSON forms. + */ + + char b = string.charAt(0); + if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { + try { + if (string.indexOf('.') > -1 || + string.indexOf('e') > -1 || string.indexOf('E') > -1) { + d = Double.valueOf(string); + if (!d.isInfinite() && !d.isNaN()) { + return d; + } + } else { + Long myLong = new Long(string); + if (myLong.longValue() == myLong.intValue()) { + return new Integer(myLong.intValue()); + } else { + return myLong; + } + } + } catch (Exception ignore) { + } + } + return string; + } + + + /** + * Throw an exception if the object is a NaN or infinite number. + * @param o The object to test. + * @throws JSONException If o is a non-finite number. + */ + public static void testValidity(Object o) throws JSONException { + if (o != null) { + if (o instanceof Double) { + if (((Double)o).isInfinite() || ((Double)o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } else if (o instanceof Float) { + if (((Float)o).isInfinite() || ((Float)o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } + } + } + + + /** + * Produce a JSONArray containing the values of the members of this + * JSONObject. + * @param names A JSONArray containing a list of key strings. This + * determines the sequence of the values in the result. + * @return A JSONArray of values. + * @throws JSONException If any of the values are non-finite numbers. + */ + public JSONArray toJSONArray(JSONArray names) throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (int i = 0; i < names.length(); i += 1) { + ja.put(this.opt(names.getString(i))); + } + return ja; + } + + /** + * Make a JSON text of this JSONObject. For compactness, no whitespace + * is added. If this would not result in a syntactically correct JSON text, + * then null will be returned instead. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, portable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + */ + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + + /** + * Make a prettyprinted JSON text of this JSONObject. + *

+ * Warning: This method assumes that the data structure is acyclical. + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @return a printable, displayable, portable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + * @throws JSONException If the object contains an invalid number. + */ + public String toString(int indentFactor) throws JSONException { + StringWriter w = new StringWriter(); + synchronized (w.getBuffer()) { + return this.write(w, indentFactor, 0).toString(); + } + } + + /** + * Make a JSON text of an Object value. If the object has an + * value.toJSONString() method, then that method will be used to produce + * the JSON text. The method is required to produce a strictly + * conforming text. If the object does not contain a toJSONString + * method (which is the most common case), then a text will be + * produced by other means. If the value is an array or Collection, + * then a JSONArray will be made from it and its toJSONString method + * will be called. If the value is a MAP, then a JSONObject will be made + * from it and its toJSONString method will be called. Otherwise, the + * value's toString method will be called, and the result will be quoted. + * + *

+ * Warning: This method assumes that the data structure is acyclical. + * @param value The value to be serialized. + * @return a printable, displayable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + * @throws JSONException If the value is or contains an invalid number. + */ + public static String valueToString(Object value) throws JSONException { + if (value == null || value.equals(null)) { + return "null"; + } + if (value instanceof JSONString) { + Object object; + try { + object = ((JSONString)value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + if (object instanceof String) { + return (String)object; + } + throw new JSONException("Bad value from toJSONString: " + object); + } + if (value instanceof Number) { + return numberToString((Number) value); + } + if (value instanceof Boolean || value instanceof JSONObject || + value instanceof JSONArray) { + return value.toString(); + } + if (value instanceof Map) { + return new JSONObject((Map)value).toString(); + } + if (value instanceof Collection) { + return new JSONArray((Collection)value).toString(); + } + if (value.getClass().isArray()) { + return new JSONArray(value).toString(); + } + return quote(value.toString()); + } + + /** + * Wrap an object, if necessary. If the object is null, return the NULL + * object. If it is an array or collection, wrap it in a JSONArray. If + * it is a map, wrap it in a JSONObject. If it is a standard property + * (Double, String, et al) then it is already wrapped. Otherwise, if it + * comes from one of the java packages, turn it into a string. And if + * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, + * then null is returned. + * + * @param object The object to wrap + * @return The wrapped value + */ + public static Object wrap(Object object) { + try { + if (object == null) { + return NULL; + } + if (object instanceof JSONObject || object instanceof JSONArray || + NULL.equals(object) || object instanceof JSONString || + object instanceof Byte || object instanceof Character || + object instanceof Short || object instanceof Integer || + object instanceof Long || object instanceof Boolean || + object instanceof Float || object instanceof Double || + object instanceof String || object instanceof Enum) { + return object; + } + + if (object instanceof Collection) { + return new JSONArray((Collection)object); + } + if (object.getClass().isArray()) { + return new JSONArray(object); + } + if (object instanceof Map) { + return new JSONObject((Map)object); + } + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null + ? objectPackage.getName() + : ""; + if ( + objectPackageName.startsWith("java.") || + objectPackageName.startsWith("javax.") || + object.getClass().getClassLoader() == null + ) { + return object.toString(); + } + return new JSONObject(object); + } catch(Exception exception) { + return null; + } + } + + + /** + * Write the contents of the JSONObject as JSON text to a writer. + * For compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + + static final Writer writeValue(Writer writer, Object value, + int indentFactor, int indent) throws JSONException, IOException { + if (value == null || value.equals(null)) { + writer.write("null"); + } else if (value instanceof JSONObject) { + ((JSONObject) value).write(writer, indentFactor, indent); + } else if (value instanceof JSONArray) { + ((JSONArray) value).write(writer, indentFactor, indent); + } else if (value instanceof Map) { + new JSONObject((Map) value).write(writer, indentFactor, indent); + } else if (value instanceof Collection) { + new JSONArray((Collection) value).write(writer, indentFactor, + indent); + } else if (value.getClass().isArray()) { + new JSONArray(value).write(writer, indentFactor, indent); + } else if (value instanceof Number) { + writer.write(numberToString((Number) value)); + } else if (value instanceof Boolean) { + writer.write(value.toString()); + } else if (value instanceof JSONString) { + Object o; + try { + o = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + writer.write(o != null ? o.toString() : quote(value.toString())); + } else { + quote(value.toString(), writer); + } + return writer; + } + + static final void indent(Writer writer, int indent) throws IOException { + for (int i = 0; i < indent; i += 1) { + writer.write(' '); + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + final int length = this.length(); + Iterator keys = this.keys(); + writer.write('{'); + + if (length == 1) { + Object key = keys.next(); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + while (keys.hasNext()) { + Object key = keys.next(); + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, newindent); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, + newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, indent); + } + writer.write('}'); + return writer; + } catch (IOException exception) { + throw new JSONException(exception); + } + } +} diff --git a/grammars/org/json/JSONString.class b/grammars/org/json/JSONString.class new file mode 100644 index 0000000000000000000000000000000000000000..329f686758d463a599abfa28eaaca9bd9cbc1e45 GIT binary patch literal 156 zcmX^0Z`VEs1_mPrPId-%b_Nbc2A-09uV8<_;F6-uymUqe5e-eBti-ZJ{hY+SbbW}Z zH6sI8aDHh~a;jTqPAVeJSONString interface allows a toJSONString() + * method so that a class can change the behavior of + * JSONObject.toString(), JSONArray.toString(), + * and JSONWriter.value(Object). The + * toJSONString method will be used instead of the default behavior + * of using the Object's toString() method and quoting the result. + */ +public interface JSONString { + /** + * The toJSONString method allows a class to produce its own JSON + * serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} diff --git a/grammars/org/json/JSONStringer.java b/grammars/org/json/JSONStringer.java new file mode 100755 index 0000000..25c2e5d --- /dev/null +++ b/grammars/org/json/JSONStringer.java @@ -0,0 +1,78 @@ +package org.json; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.StringWriter; + +/** + * JSONStringer provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONStringer can produce one JSON text. + *

+ * A JSONStringer instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting cascade style. For example,

+ * myString = new JSONStringer()
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject()
+ *     .toString();
which produces the string
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONStringer adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2008-09-18 + */ +public class JSONStringer extends JSONWriter { + /** + * Make a fresh JSONStringer. It can be used to build one JSON text. + */ + public JSONStringer() { + super(new StringWriter()); + } + + /** + * Return the JSON text. This method is used to obtain the product of the + * JSONStringer instance. It will return null if there was a + * problem in the construction of the JSON text (such as the calls to + * array were not properly balanced with calls to + * endArray). + * @return The JSON text. + */ + public String toString() { + return this.mode == 'd' ? this.writer.toString() : null; + } +} diff --git a/grammars/org/json/JSONTokener.class b/grammars/org/json/JSONTokener.class new file mode 100644 index 0000000000000000000000000000000000000000..f886bccd67a198d4bf1ea742ab6390dc08d47cae GIT binary patch literal 5033 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 B8wLOX literal 0 HcmV?d00001 diff --git a/grammars/org/json/JSONTokener.java b/grammars/org/json/JSONTokener.java new file mode 100644 index 0000000..13c84f1 --- /dev/null +++ b/grammars/org/json/JSONTokener.java @@ -0,0 +1,446 @@ +package org.json; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * A JSONTokener takes a source string and extracts characters and tokens from + * it. It is used by the JSONObject and JSONArray constructors to parse + * JSON source strings. + * @author JSON.org + * @version 2012-02-16 + */ +public class JSONTokener { + + private long character; + private boolean eof; + private long index; + private long line; + private char previous; + private Reader reader; + private boolean usePrevious; + + + /** + * Construct a JSONTokener from a Reader. + * + * @param reader A reader. + */ + public JSONTokener(Reader reader) { + this.reader = reader.markSupported() + ? reader + : new BufferedReader(reader); + this.eof = false; + this.usePrevious = false; + this.previous = 0; + this.index = 0; + this.character = 1; + this.line = 1; + } + + + /** + * Construct a JSONTokener from an InputStream. + */ + public JSONTokener(InputStream inputStream) throws JSONException { + this(new InputStreamReader(inputStream)); + } + + + /** + * Construct a JSONTokener from a string. + * + * @param s A source string. + */ + public JSONTokener(String s) { + this(new StringReader(s)); + } + + + /** + * Back up one character. This provides a sort of lookahead capability, + * so that you can test for a digit or letter before attempting to parse + * the next number or identifier. + */ + public void back() throws JSONException { + if (this.usePrevious || this.index <= 0) { + throw new JSONException("Stepping back two steps is not supported"); + } + this.index -= 1; + this.character -= 1; + this.usePrevious = true; + this.eof = false; + } + + + /** + * Get the hex value of a character (base16). + * @param c A character between '0' and '9' or between 'A' and 'F' or + * between 'a' and 'f'. + * @return An int between 0 and 15, or -1 if c was not a hex digit. + */ + public static int dehexchar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + if (c >= 'A' && c <= 'F') { + return c - ('A' - 10); + } + if (c >= 'a' && c <= 'f') { + return c - ('a' - 10); + } + return -1; + } + + public boolean end() { + return this.eof && !this.usePrevious; + } + + + /** + * Determine if the source string still contains characters that next() + * can consume. + * @return true if not yet at the end of the source. + */ + public boolean more() throws JSONException { + this.next(); + if (this.end()) { + return false; + } + this.back(); + return true; + } + + + /** + * Get the next character in the source string. + * + * @return The next character, or 0 if past the end of the source string. + */ + public char next() throws JSONException { + int c; + if (this.usePrevious) { + this.usePrevious = false; + c = this.previous; + } else { + try { + c = this.reader.read(); + } catch (IOException exception) { + throw new JSONException(exception); + } + + if (c <= 0) { // End of stream + this.eof = true; + c = 0; + } + } + this.index += 1; + if (this.previous == '\r') { + this.line += 1; + this.character = c == '\n' ? 0 : 1; + } else if (c == '\n') { + this.line += 1; + this.character = 0; + } else { + this.character += 1; + } + this.previous = (char) c; + return this.previous; + } + + + /** + * Consume the next character, and check that it matches a specified + * character. + * @param c The character to match. + * @return The character. + * @throws JSONException if the character does not match. + */ + public char next(char c) throws JSONException { + char n = this.next(); + if (n != c) { + throw this.syntaxError("Expected '" + c + "' and instead saw '" + + n + "'"); + } + return n; + } + + + /** + * Get the next n characters. + * + * @param n The number of characters to take. + * @return A string of n characters. + * @throws JSONException + * Substring bounds error if there are not + * n characters remaining in the source string. + */ + public String next(int n) throws JSONException { + if (n == 0) { + return ""; + } + + char[] chars = new char[n]; + int pos = 0; + + while (pos < n) { + chars[pos] = this.next(); + if (this.end()) { + throw this.syntaxError("Substring bounds error"); + } + pos += 1; + } + return new String(chars); + } + + + /** + * Get the next char in the string, skipping whitespace. + * @throws JSONException + * @return A character, or 0 if there are no more characters. + */ + public char nextClean() throws JSONException { + for (;;) { + char c = this.next(); + if (c == 0 || c > ' ') { + return c; + } + } + } + + + /** + * Return the characters up to the next close quote character. + * Backslash processing is done. The formal JSON format does not + * allow strings in single quotes, but an implementation is allowed to + * accept them. + * @param quote The quoting character, either + * " (double quote) or + * ' (single quote). + * @return A String. + * @throws JSONException Unterminated string. + */ + public String nextString(char quote) throws JSONException { + char c; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = this.next(); + switch (c) { + case 0: + case '\n': + case '\r': + throw this.syntaxError("Unterminated string"); + case '\\': + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + sb.append((char)Integer.parseInt(this.next(4), 16)); + break; + case '"': + case '\'': + case '\\': + case '/': + sb.append(c); + break; + default: + throw this.syntaxError("Illegal escape."); + } + break; + default: + if (c == quote) { + return sb.toString(); + } + sb.append(c); + } + } + } + + + /** + * Get the text up but not including the specified character or the + * end of line, whichever comes first. + * @param delimiter A delimiter character. + * @return A string. + */ + public String nextTo(char delimiter) throws JSONException { + StringBuffer sb = new StringBuffer(); + for (;;) { + char c = this.next(); + if (c == delimiter || c == 0 || c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the text up but not including one of the specified delimiter + * characters or the end of line, whichever comes first. + * @param delimiters A set of delimiter characters. + * @return A string, trimmed. + */ + public String nextTo(String delimiters) throws JSONException { + char c; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = this.next(); + if (delimiters.indexOf(c) >= 0 || c == 0 || + c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the next value. The value can be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. + * @throws JSONException If syntax error. + * + * @return An object. + */ + public Object nextValue() throws JSONException { + char c = this.nextClean(); + String string; + + switch (c) { + case '"': + case '\'': + return this.nextString(c); + case '{': + this.back(); + return new JSONObject(this); + case '[': + this.back(); + return new JSONArray(this); + } + + /* + * Handle unquoted text. This could be the values true, false, or + * null, or it can be a number. An implementation (such as this one) + * is allowed to also accept non-standard forms. + * + * Accumulate characters until we reach the end of the text or a + * formatting character. + */ + + StringBuffer sb = new StringBuffer(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = this.next(); + } + this.back(); + + string = sb.toString().trim(); + if ("".equals(string)) { + throw this.syntaxError("Missing value"); + } + return JSONObject.stringToValue(string); + } + + + /** + * Skip characters until the next character is the requested character. + * If the requested character is not found, no characters are skipped. + * @param to A character to skip to. + * @return The requested character, or zero if the requested character + * is not found. + */ + public char skipTo(char to) throws JSONException { + char c; + try { + long startIndex = this.index; + long startCharacter = this.character; + long startLine = this.line; + this.reader.mark(1000000); + do { + c = this.next(); + if (c == 0) { + this.reader.reset(); + this.index = startIndex; + this.character = startCharacter; + this.line = startLine; + return c; + } + } while (c != to); + } catch (IOException exc) { + throw new JSONException(exc); + } + + this.back(); + return c; + } + + + /** + * Make a JSONException to signal a syntax error. + * + * @param message The error message. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this.toString()); + } + + + /** + * Make a printable string of this JSONTokener. + * + * @return " at {index} [character {character} line {line}]" + */ + public String toString() { + return " at " + this.index + " [character " + this.character + " line " + + this.line + "]"; + } +} diff --git a/grammars/org/json/JSONWriter.java b/grammars/org/json/JSONWriter.java new file mode 100755 index 0000000..855b2bd --- /dev/null +++ b/grammars/org/json/JSONWriter.java @@ -0,0 +1,327 @@ +package org.json; + +import java.io.IOException; +import java.io.Writer; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * JSONWriter provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONWriter can produce one JSON text. + *

+ * A JSONWriter instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting a cascade style. For example,

+ * new JSONWriter(myWriter)
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject();
which writes
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONWriter adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2011-11-24 + */ +public class JSONWriter { + private static final int maxdepth = 200; + + /** + * The comma flag determines if a comma should be output before the next + * value. + */ + private boolean comma; + + /** + * The current mode. Values: + * 'a' (array), + * 'd' (done), + * 'i' (initial), + * 'k' (key), + * 'o' (object). + */ + protected char mode; + + /** + * The object/array stack. + */ + private final JSONObject stack[]; + + /** + * The stack top index. A value of 0 indicates that the stack is empty. + */ + private int top; + + /** + * The writer that will receive the output. + */ + protected Writer writer; + + /** + * Make a fresh JSONWriter. It can be used to build one JSON text. + */ + public JSONWriter(Writer w) { + this.comma = false; + this.mode = 'i'; + this.stack = new JSONObject[maxdepth]; + this.top = 0; + this.writer = w; + } + + /** + * Append a value. + * @param string A string value. + * @return this + * @throws JSONException If the value is out of sequence. + */ + private JSONWriter append(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null pointer"); + } + if (this.mode == 'o' || this.mode == 'a') { + try { + if (this.comma && this.mode == 'a') { + this.writer.write(','); + } + this.writer.write(string); + } catch (IOException e) { + throw new JSONException(e); + } + if (this.mode == 'o') { + this.mode = 'k'; + } + this.comma = true; + return this; + } + throw new JSONException("Value out of sequence."); + } + + /** + * Begin appending a new array. All values until the balancing + * endArray will be appended to this array. The + * endArray method must be called to mark the array's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter array() throws JSONException { + if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { + this.push(null); + this.append("["); + this.comma = false; + return this; + } + throw new JSONException("Misplaced array."); + } + + /** + * End something. + * @param mode Mode + * @param c Closing character + * @return this + * @throws JSONException If unbalanced. + */ + private JSONWriter end(char mode, char c) throws JSONException { + if (this.mode != mode) { + throw new JSONException(mode == 'a' + ? "Misplaced endArray." + : "Misplaced endObject."); + } + this.pop(mode); + try { + this.writer.write(c); + } catch (IOException e) { + throw new JSONException(e); + } + this.comma = true; + return this; + } + + /** + * End an array. This method most be called to balance calls to + * array. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endArray() throws JSONException { + return this.end('a', ']'); + } + + /** + * End an object. This method most be called to balance calls to + * object. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endObject() throws JSONException { + return this.end('k', '}'); + } + + /** + * Append a key. The key will be associated with the next value. In an + * object, every value must be preceded by a key. + * @param string A key string. + * @return this + * @throws JSONException If the key is out of place. For example, keys + * do not belong in arrays or if the key is null. + */ + public JSONWriter key(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null key."); + } + if (this.mode == 'k') { + try { + this.stack[this.top - 1].putOnce(string, Boolean.TRUE); + if (this.comma) { + this.writer.write(','); + } + this.writer.write(JSONObject.quote(string)); + this.writer.write(':'); + this.comma = false; + this.mode = 'o'; + return this; + } catch (IOException e) { + throw new JSONException(e); + } + } + throw new JSONException("Misplaced key."); + } + + + /** + * Begin appending a new object. All keys and values until the balancing + * endObject will be appended to this object. The + * endObject method must be called to mark the object's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter object() throws JSONException { + if (this.mode == 'i') { + this.mode = 'o'; + } + if (this.mode == 'o' || this.mode == 'a') { + this.append("{"); + this.push(new JSONObject()); + this.comma = false; + return this; + } + throw new JSONException("Misplaced object."); + + } + + + /** + * Pop an array or object scope. + * @param c The scope to close. + * @throws JSONException If nesting is wrong. + */ + private void pop(char c) throws JSONException { + if (this.top <= 0) { + throw new JSONException("Nesting error."); + } + char m = this.stack[this.top - 1] == null ? 'a' : 'k'; + if (m != c) { + throw new JSONException("Nesting error."); + } + this.top -= 1; + this.mode = this.top == 0 + ? 'd' + : this.stack[this.top - 1] == null + ? 'a' + : 'k'; + } + + /** + * Push an array or object scope. + * @param c The scope to open. + * @throws JSONException If nesting is too deep. + */ + private void push(JSONObject jo) throws JSONException { + if (this.top >= maxdepth) { + throw new JSONException("Nesting too deep."); + } + this.stack[this.top] = jo; + this.mode = jo == null ? 'a' : 'k'; + this.top += 1; + } + + + /** + * Append either the value true or the value + * false. + * @param b A boolean. + * @return this + * @throws JSONException + */ + public JSONWriter value(boolean b) throws JSONException { + return this.append(b ? "true" : "false"); + } + + /** + * Append a double value. + * @param d A double. + * @return this + * @throws JSONException If the number is not finite. + */ + public JSONWriter value(double d) throws JSONException { + return this.value(new Double(d)); + } + + /** + * Append a long value. + * @param l A long. + * @return this + * @throws JSONException + */ + public JSONWriter value(long l) throws JSONException { + return this.append(Long.toString(l)); + } + + + /** + * Append an object value. + * @param object The object to append. It can be null, or a Boolean, Number, + * String, JSONObject, or JSONArray, or an object that implements JSONString. + * @return this + * @throws JSONException If the value is out of sequence. + */ + public JSONWriter value(Object object) throws JSONException { + return this.append(JSONObject.valueToString(object)); + } +} diff --git a/grammars/org/json/XML.java b/grammars/org/json/XML.java new file mode 100755 index 0000000..82455b3 --- /dev/null +++ b/grammars/org/json/XML.java @@ -0,0 +1,508 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + + +/** + * This provides static methods to convert an XML text into a JSONObject, + * and to covert a JSONObject into an XML text. + * @author JSON.org + * @version 2011-02-11 + */ +public class XML { + + /** The Character '&'. */ + public static final Character AMP = new Character('&'); + + /** The Character '''. */ + public static final Character APOS = new Character('\''); + + /** The Character '!'. */ + public static final Character BANG = new Character('!'); + + /** The Character '='. */ + public static final Character EQ = new Character('='); + + /** The Character '>'. */ + public static final Character GT = new Character('>'); + + /** The Character '<'. */ + public static final Character LT = new Character('<'); + + /** The Character '?'. */ + public static final Character QUEST = new Character('?'); + + /** The Character '"'. */ + public static final Character QUOT = new Character('"'); + + /** The Character '/'. */ + public static final Character SLASH = new Character('/'); + + /** + * Replace special characters with XML escapes: + *

+     * & (ampersand) is replaced by &amp;
+     * < (less than) is replaced by &lt;
+     * > (greater than) is replaced by &gt;
+     * " (double quote) is replaced by &quot;
+     * 
+ * @param string The string to be escaped. + * @return The escaped string. + */ + public static String escape(String string) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, length = string.length(); i < length; i++) { + char c = string.charAt(i); + switch (c) { + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '"': + sb.append("""); + break; + case '\'': + sb.append("'"); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + + /** + * Throw an exception if the string contains whitespace. + * Whitespace is not allowed in tagNames and attributes. + * @param string + * @throws JSONException + */ + public static void noSpace(String string) throws JSONException { + int i, length = string.length(); + if (length == 0) { + throw new JSONException("Empty string."); + } + for (i = 0; i < length; i += 1) { + if (Character.isWhitespace(string.charAt(i))) { + throw new JSONException("'" + string + + "' contains a space character."); + } + } + } + + /** + * Scan the content following the named tag, attaching it to the context. + * @param x The XMLTokener containing the source string. + * @param context The JSONObject that will include the new material. + * @param name The tag name. + * @return true if the close tag is processed. + * @throws JSONException + */ + private static boolean parse(XMLTokener x, JSONObject context, + String name) throws JSONException { + char c; + int i; + JSONObject jsonobject = null; + String string; + String tagName; + Object token; + +// Test for and skip past these forms: +// +// +// +// +// Report errors for these forms: +// <> +// <= +// << + + token = x.nextToken(); + +// "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate("content", string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + +// "); + return false; + } else if (token == SLASH) { + +// Close tag + + } else if (token == SLASH) { + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped tag"); + } + if (jsonobject.length() > 0) { + context.accumulate(tagName, jsonobject); + } else { + context.accumulate(tagName, ""); + } + return false; + +// Content, between <...> and + + } else if (token == GT) { + for (;;) { + token = x.nextContent(); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String)token; + if (string.length() > 0) { + jsonobject.accumulate("content", + XML.stringToValue(string)); + } + +// Nested element + + } else if (token == LT) { + if (parse(x, jsonobject, tagName)) { + if (jsonobject.length() == 0) { + context.accumulate(tagName, ""); + } else if (jsonobject.length() == 1 && + jsonobject.opt("content") != null) { + context.accumulate(tagName, + jsonobject.opt("content")); + } else { + context.accumulate(tagName, jsonobject); + } + return false; + } + } + } + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. This is much less ambitious than + * JSONObject.stringToValue, especially because it does not attempt to + * convert plus forms, octal forms, hex forms, or E forms lacking decimal + * points. + * @param string A String. + * @return A simple JSON value. + */ + public static Object stringToValue(String string) { + if ("".equals(string)) { + return string; + } + if ("true".equalsIgnoreCase(string)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(string)) { + return Boolean.FALSE; + } + if ("null".equalsIgnoreCase(string)) { + return JSONObject.NULL; + } + if ("0".equals(string)) { + return new Integer(0); + } + +// If it might be a number, try converting it. If that doesn't work, +// return the string. + + try { + char initial = string.charAt(0); + boolean negative = false; + if (initial == '-') { + initial = string.charAt(1); + negative = true; + } + if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') { + return string; + } + if ((initial >= '0' && initial <= '9')) { + if (string.indexOf('.') >= 0) { + return Double.valueOf(string); + } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) { + Long myLong = new Long(string); + if (myLong.longValue() == myLong.intValue()) { + return new Integer(myLong.intValue()); + } else { + return myLong; + } + } + } + } catch (Exception ignore) { + } + return string; + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation + * because JSON is a data format and XML is a document format. XML uses + * elements, attributes, and content text, while JSON uses unordered + * collections of name/value pairs and arrays of values. JSON does not + * does not like to distinguish between elements and attributes. + * Sequences of similar elements are represented as JSONArrays. Content + * text may be placed in a "content" member. Comments, prologs, DTDs, and + * <[ [ ]]> are ignored. + * @param string The source string. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(string); + while (x.more() && x.skipPast("<")) { + parse(x, jo, null); + } + return jo; + } + + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * @param object A JSONObject. + * @return A string. + * @throws JSONException + */ + public static String toString(Object object) throws JSONException { + return toString(object, null); + } + + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @return A string. + * @throws JSONException + */ + public static String toString(Object object, String tagName) + throws JSONException { + StringBuffer sb = new StringBuffer(); + int i; + JSONArray ja; + JSONObject jo; + String key; + Iterator keys; + int length; + String string; + Object value; + if (object instanceof JSONObject) { + +// Emit + + if (tagName != null) { + sb.append('<'); + sb.append(tagName); + sb.append('>'); + } + +// Loop thru the keys. + + jo = (JSONObject)object; + keys = jo.keys(); + while (keys.hasNext()) { + key = keys.next().toString(); + value = jo.opt(key); + if (value == null) { + value = ""; + } + if (value instanceof String) { + string = (String)value; + } else { + string = null; + } + +// Emit content in body + + if ("content".equals(key)) { + if (value instanceof JSONArray) { + ja = (JSONArray)value; + length = ja.length(); + for (i = 0; i < length; i += 1) { + if (i > 0) { + sb.append('\n'); + } + sb.append(escape(ja.get(i).toString())); + } + } else { + sb.append(escape(value.toString())); + } + +// Emit an array of similar keys + + } else if (value instanceof JSONArray) { + ja = (JSONArray)value; + length = ja.length(); + for (i = 0; i < length; i += 1) { + value = ja.get(i); + if (value instanceof JSONArray) { + sb.append('<'); + sb.append(key); + sb.append('>'); + sb.append(toString(value)); + sb.append("'); + } else { + sb.append(toString(value, key)); + } + } + } else if ("".equals(value)) { + sb.append('<'); + sb.append(key); + sb.append("/>"); + +// Emit a new tag + + } else { + sb.append(toString(value, key)); + } + } + if (tagName != null) { + +// Emit the close tag + + sb.append("'); + } + return sb.toString(); + +// XML does not have good support for arrays. If an array appears in a place +// where XML is lacking, synthesize an element. + + } else { + if (object.getClass().isArray()) { + object = new JSONArray(object); + } + if (object instanceof JSONArray) { + ja = (JSONArray)object; + length = ja.length(); + for (i = 0; i < length; i += 1) { + sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); + } + return sb.toString(); + } else { + string = (object == null) ? "null" : escape(object.toString()); + return (tagName == null) ? "\"" + string + "\"" : + (string.length() == 0) ? "<" + tagName + "/>" : + "<" + tagName + ">" + string + ""; + } + } + } +} \ No newline at end of file diff --git a/grammars/org/json/XMLTokener.java b/grammars/org/json/XMLTokener.java new file mode 100755 index 0000000..07574b0 --- /dev/null +++ b/grammars/org/json/XMLTokener.java @@ -0,0 +1,365 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The XMLTokener extends the JSONTokener to provide additional methods + * for the parsing of XML texts. + * @author JSON.org + * @version 2010-12-24 + */ +public class XMLTokener extends JSONTokener { + + + /** The table of entity values. It initially contains Character values for + * amp, apos, gt, lt, quot. + */ + public static final java.util.HashMap entity; + + static { + entity = new java.util.HashMap(8); + entity.put("amp", XML.AMP); + entity.put("apos", XML.APOS); + entity.put("gt", XML.GT); + entity.put("lt", XML.LT); + entity.put("quot", XML.QUOT); + } + + /** + * Construct an XMLTokener from a string. + * @param s A source string. + */ + public XMLTokener(String s) { + super(s); + } + + /** + * Get the text in the CDATA block. + * @return The string up to the ]]>. + * @throws JSONException If the ]]> is not found. + */ + public String nextCDATA() throws JSONException { + char c; + int i; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = next(); + if (end()) { + throw syntaxError("Unclosed CDATA"); + } + sb.append(c); + i = sb.length() - 3; + if (i >= 0 && sb.charAt(i) == ']' && + sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { + sb.setLength(i); + return sb.toString(); + } + } + } + + + /** + * Get the next XML outer token, trimming whitespace. There are two kinds + * of tokens: the '<' character which begins a markup tag, and the content + * text between markup tags. + * + * @return A string, or a '<' Character, or null if there is no more + * source text. + * @throws JSONException + */ + public Object nextContent() throws JSONException { + char c; + StringBuffer sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == 0) { + return null; + } + if (c == '<') { + return XML.LT; + } + sb = new StringBuffer(); + for (;;) { + if (c == '<' || c == 0) { + back(); + return sb.toString().trim(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + c = next(); + } + } + + + /** + * Return the next entity. These entities are translated to Characters: + * & ' > < ". + * @param ampersand An ampersand character. + * @return A Character or an entity String if the entity is not recognized. + * @throws JSONException If missing ';' in XML entity. + */ + public Object nextEntity(char ampersand) throws JSONException { + StringBuffer sb = new StringBuffer(); + for (;;) { + char c = next(); + if (Character.isLetterOrDigit(c) || c == '#') { + sb.append(Character.toLowerCase(c)); + } else if (c == ';') { + break; + } else { + throw syntaxError("Missing ';' in XML entity: &" + sb); + } + } + String string = sb.toString(); + Object object = entity.get(string); + return object != null ? object : ampersand + string + ";"; + } + + + /** + * Returns the next XML meta token. This is used for skipping over + * and structures. + * @return Syntax characters (< > / = ! ?) are returned as + * Character, and strings and names are returned as Boolean. We don't care + * what the values actually are. + * @throws JSONException If a string is not properly closed or if the XML + * is badly structured. + */ + public Object nextMeta() throws JSONException { + char c; + char q; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped meta tag"); + case '<': + return XML.LT; + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + case '"': + case '\'': + q = c; + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return Boolean.TRUE; + } + } + default: + for (;;) { + c = next(); + if (Character.isWhitespace(c)) { + return Boolean.TRUE; + } + switch (c) { + case 0: + case '<': + case '>': + case '/': + case '=': + case '!': + case '?': + case '"': + case '\'': + back(); + return Boolean.TRUE; + } + } + } + } + + + /** + * Get the next XML Token. These tokens are found inside of angle + * brackets. It may be one of these characters: / > = ! ? or it + * may be a string wrapped in single quotes or double quotes, or it may be a + * name. + * @return a String or a Character. + * @throws JSONException If the XML is not well formed. + */ + public Object nextToken() throws JSONException { + char c; + char q; + StringBuffer sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped element"); + case '<': + throw syntaxError("Misplaced '<'"); + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + +// Quoted string + + case '"': + case '\'': + q = c; + sb = new StringBuffer(); + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return sb.toString(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + } + default: + +// Name + + sb = new StringBuffer(); + for (;;) { + sb.append(c); + c = next(); + if (Character.isWhitespace(c)) { + return sb.toString(); + } + switch (c) { + case 0: + return sb.toString(); + case '>': + case '/': + case '=': + case '!': + case '?': + case '[': + case ']': + back(); + return sb.toString(); + case '<': + case '"': + case '\'': + throw syntaxError("Bad character in a name"); + } + } + } + } + + + /** + * Skip characters until past the requested string. + * If it is not found, we are left at the end of the source with a result of false. + * @param to A string to skip past. + * @throws JSONException + */ + public boolean skipPast(String to) throws JSONException { + boolean b; + char c; + int i; + int j; + int offset = 0; + int length = to.length(); + char[] circle = new char[length]; + + /* + * First fill the circle buffer with as many characters as are in the + * to string. If we reach an early end, bail. + */ + + for (i = 0; i < length; i += 1) { + c = next(); + if (c == 0) { + return false; + } + circle[i] = c; + } + /* + * We will loop, possibly for all of the remaining characters. + */ + for (;;) { + j = offset; + b = true; + /* + * Compare the circle buffer with the to string. + */ + for (i = 0; i < length; i += 1) { + if (circle[j] != to.charAt(i)) { + b = false; + break; + } + j += 1; + if (j >= length) { + j -= length; + } + } + /* + * If we exit the loop with b intact, then victory is ours. + */ + if (b) { + return true; + } + /* + * Get the next character. If there isn't one, then defeat is ours. + */ + c = next(); + if (c == 0) { + return false; + } + /* + * Shove the character in the circle buffer and advance the + * circle offset. The offset is mod n. + */ + circle[offset] = c; + offset += 1; + if (offset >= length) { + offset -= length; + } + } + } +} From 913da0b8d302e66d002e87fe7294662620f12266 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 23:11:50 -0400 Subject: [PATCH 007/140] updating the test command lines --- grammars/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/grammars/test.sh b/grammars/test.sh index 4377a72..955dfa8 100644 --- a/grammars/test.sh +++ b/grammars/test.sh @@ -1 +1,2 @@ cat 1.wdl | python Lexer.py | python ParserMain.py wdl ast +java Lexer 3.wdl > tokens ; cat tokens | java ParserMain wdl ast From da43b1d08ae9cf1f0c966092b631e0b7d664ce04 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 31 Jul 2012 23:15:37 -0400 Subject: [PATCH 008/140] renaming grammars -> test --- {grammars => test}/1.wdl | 0 {grammars => test}/2.wdl | 0 {grammars => test}/3.wdl | 0 {grammars => test}/Ast.java | 0 {grammars => test}/AstList.java | 0 {grammars => test}/AstNode.java | 0 {grammars => test}/AstTransform.java | 0 {grammars => test}/AstTransformNodeCreator.java | 0 {grammars => test}/AstTransformSubstitution.java | 0 {grammars => test}/ExpressionParser.java | 0 {grammars => test}/Lexer.java | 0 {grammars => test}/Lexer.py | 0 {grammars => test}/NonTerminal.java | 0 {grammars => test}/ParseTree.java | 0 {grammars => test}/ParseTreeNode.java | 0 {grammars => test}/Parser.java | 0 {grammars => test}/ParserCommon.py | 0 {grammars => test}/ParserMain.java | 0 {grammars => test}/ParserMain.py | 0 {grammars => test}/SyntaxError.java | 0 {grammars => test}/Terminal.java | 0 {grammars => test}/TerminalMap.java | 0 {grammars => test}/TokenStream.java | 0 {grammars => test}/Utility.java | 0 {grammars => test}/WdlParser.java | 0 {grammars => test}/org/json/CDL.java | 0 {grammars => test}/org/json/Cookie.java | 0 {grammars => test}/org/json/CookieList.java | 0 {grammars => test}/org/json/HTTP.java | 0 {grammars => test}/org/json/HTTPTokener.java | 0 {grammars => test}/org/json/JSONArray.class | Bin {grammars => test}/org/json/JSONArray.java | 0 {grammars => test}/org/json/JSONException.class | Bin {grammars => test}/org/json/JSONException.java | 0 {grammars => test}/org/json/JSONML.java | 0 {grammars => test}/org/json/JSONObject$1.class | Bin {grammars => test}/org/json/JSONObject$Null.class | Bin {grammars => test}/org/json/JSONObject.class | Bin {grammars => test}/org/json/JSONObject.java | 0 {grammars => test}/org/json/JSONString.class | Bin {grammars => test}/org/json/JSONString.java | 0 {grammars => test}/org/json/JSONStringer.java | 0 {grammars => test}/org/json/JSONTokener.class | Bin {grammars => test}/org/json/JSONTokener.java | 0 {grammars => test}/org/json/JSONWriter.java | 0 {grammars => test}/org/json/XML.java | 0 {grammars => test}/org/json/XMLTokener.java | 0 {grammars => test}/test.sh | 0 {grammars => test}/wdl.zgr | 0 {grammars => test}/wdl_Parser.py | 0 50 files changed, 0 insertions(+), 0 deletions(-) rename {grammars => test}/1.wdl (100%) rename {grammars => test}/2.wdl (100%) rename {grammars => test}/3.wdl (100%) rename {grammars => test}/Ast.java (100%) rename {grammars => test}/AstList.java (100%) rename {grammars => test}/AstNode.java (100%) rename {grammars => test}/AstTransform.java (100%) rename {grammars => test}/AstTransformNodeCreator.java (100%) rename {grammars => test}/AstTransformSubstitution.java (100%) rename {grammars => test}/ExpressionParser.java (100%) rename {grammars => test}/Lexer.java (100%) rename {grammars => test}/Lexer.py (100%) rename {grammars => test}/NonTerminal.java (100%) rename {grammars => test}/ParseTree.java (100%) rename {grammars => test}/ParseTreeNode.java (100%) rename {grammars => test}/Parser.java (100%) rename {grammars => test}/ParserCommon.py (100%) rename {grammars => test}/ParserMain.java (100%) rename {grammars => test}/ParserMain.py (100%) rename {grammars => test}/SyntaxError.java (100%) rename {grammars => test}/Terminal.java (100%) rename {grammars => test}/TerminalMap.java (100%) rename {grammars => test}/TokenStream.java (100%) rename {grammars => test}/Utility.java (100%) rename {grammars => test}/WdlParser.java (100%) rename {grammars => test}/org/json/CDL.java (100%) rename {grammars => test}/org/json/Cookie.java (100%) rename {grammars => test}/org/json/CookieList.java (100%) rename {grammars => test}/org/json/HTTP.java (100%) rename {grammars => test}/org/json/HTTPTokener.java (100%) rename {grammars => test}/org/json/JSONArray.class (100%) rename {grammars => test}/org/json/JSONArray.java (100%) rename {grammars => test}/org/json/JSONException.class (100%) rename {grammars => test}/org/json/JSONException.java (100%) rename {grammars => test}/org/json/JSONML.java (100%) rename {grammars => test}/org/json/JSONObject$1.class (100%) rename {grammars => test}/org/json/JSONObject$Null.class (100%) rename {grammars => test}/org/json/JSONObject.class (100%) rename {grammars => test}/org/json/JSONObject.java (100%) rename {grammars => test}/org/json/JSONString.class (100%) rename {grammars => test}/org/json/JSONString.java (100%) rename {grammars => test}/org/json/JSONStringer.java (100%) rename {grammars => test}/org/json/JSONTokener.class (100%) rename {grammars => test}/org/json/JSONTokener.java (100%) rename {grammars => test}/org/json/JSONWriter.java (100%) rename {grammars => test}/org/json/XML.java (100%) rename {grammars => test}/org/json/XMLTokener.java (100%) rename {grammars => test}/test.sh (100%) rename {grammars => test}/wdl.zgr (100%) rename {grammars => test}/wdl_Parser.py (100%) diff --git a/grammars/1.wdl b/test/1.wdl similarity index 100% rename from grammars/1.wdl rename to test/1.wdl diff --git a/grammars/2.wdl b/test/2.wdl similarity index 100% rename from grammars/2.wdl rename to test/2.wdl diff --git a/grammars/3.wdl b/test/3.wdl similarity index 100% rename from grammars/3.wdl rename to test/3.wdl diff --git a/grammars/Ast.java b/test/Ast.java similarity index 100% rename from grammars/Ast.java rename to test/Ast.java diff --git a/grammars/AstList.java b/test/AstList.java similarity index 100% rename from grammars/AstList.java rename to test/AstList.java diff --git a/grammars/AstNode.java b/test/AstNode.java similarity index 100% rename from grammars/AstNode.java rename to test/AstNode.java diff --git a/grammars/AstTransform.java b/test/AstTransform.java similarity index 100% rename from grammars/AstTransform.java rename to test/AstTransform.java diff --git a/grammars/AstTransformNodeCreator.java b/test/AstTransformNodeCreator.java similarity index 100% rename from grammars/AstTransformNodeCreator.java rename to test/AstTransformNodeCreator.java diff --git a/grammars/AstTransformSubstitution.java b/test/AstTransformSubstitution.java similarity index 100% rename from grammars/AstTransformSubstitution.java rename to test/AstTransformSubstitution.java diff --git a/grammars/ExpressionParser.java b/test/ExpressionParser.java similarity index 100% rename from grammars/ExpressionParser.java rename to test/ExpressionParser.java diff --git a/grammars/Lexer.java b/test/Lexer.java similarity index 100% rename from grammars/Lexer.java rename to test/Lexer.java diff --git a/grammars/Lexer.py b/test/Lexer.py similarity index 100% rename from grammars/Lexer.py rename to test/Lexer.py diff --git a/grammars/NonTerminal.java b/test/NonTerminal.java similarity index 100% rename from grammars/NonTerminal.java rename to test/NonTerminal.java diff --git a/grammars/ParseTree.java b/test/ParseTree.java similarity index 100% rename from grammars/ParseTree.java rename to test/ParseTree.java diff --git a/grammars/ParseTreeNode.java b/test/ParseTreeNode.java similarity index 100% rename from grammars/ParseTreeNode.java rename to test/ParseTreeNode.java diff --git a/grammars/Parser.java b/test/Parser.java similarity index 100% rename from grammars/Parser.java rename to test/Parser.java diff --git a/grammars/ParserCommon.py b/test/ParserCommon.py similarity index 100% rename from grammars/ParserCommon.py rename to test/ParserCommon.py diff --git a/grammars/ParserMain.java b/test/ParserMain.java similarity index 100% rename from grammars/ParserMain.java rename to test/ParserMain.java diff --git a/grammars/ParserMain.py b/test/ParserMain.py similarity index 100% rename from grammars/ParserMain.py rename to test/ParserMain.py diff --git a/grammars/SyntaxError.java b/test/SyntaxError.java similarity index 100% rename from grammars/SyntaxError.java rename to test/SyntaxError.java diff --git a/grammars/Terminal.java b/test/Terminal.java similarity index 100% rename from grammars/Terminal.java rename to test/Terminal.java diff --git a/grammars/TerminalMap.java b/test/TerminalMap.java similarity index 100% rename from grammars/TerminalMap.java rename to test/TerminalMap.java diff --git a/grammars/TokenStream.java b/test/TokenStream.java similarity index 100% rename from grammars/TokenStream.java rename to test/TokenStream.java diff --git a/grammars/Utility.java b/test/Utility.java similarity index 100% rename from grammars/Utility.java rename to test/Utility.java diff --git a/grammars/WdlParser.java b/test/WdlParser.java similarity index 100% rename from grammars/WdlParser.java rename to test/WdlParser.java diff --git a/grammars/org/json/CDL.java b/test/org/json/CDL.java similarity index 100% rename from grammars/org/json/CDL.java rename to test/org/json/CDL.java diff --git a/grammars/org/json/Cookie.java b/test/org/json/Cookie.java similarity index 100% rename from grammars/org/json/Cookie.java rename to test/org/json/Cookie.java diff --git a/grammars/org/json/CookieList.java b/test/org/json/CookieList.java similarity index 100% rename from grammars/org/json/CookieList.java rename to test/org/json/CookieList.java diff --git a/grammars/org/json/HTTP.java b/test/org/json/HTTP.java similarity index 100% rename from grammars/org/json/HTTP.java rename to test/org/json/HTTP.java diff --git a/grammars/org/json/HTTPTokener.java b/test/org/json/HTTPTokener.java similarity index 100% rename from grammars/org/json/HTTPTokener.java rename to test/org/json/HTTPTokener.java diff --git a/grammars/org/json/JSONArray.class b/test/org/json/JSONArray.class similarity index 100% rename from grammars/org/json/JSONArray.class rename to test/org/json/JSONArray.class diff --git a/grammars/org/json/JSONArray.java b/test/org/json/JSONArray.java similarity index 100% rename from grammars/org/json/JSONArray.java rename to test/org/json/JSONArray.java diff --git a/grammars/org/json/JSONException.class b/test/org/json/JSONException.class similarity index 100% rename from grammars/org/json/JSONException.class rename to test/org/json/JSONException.class diff --git a/grammars/org/json/JSONException.java b/test/org/json/JSONException.java similarity index 100% rename from grammars/org/json/JSONException.java rename to test/org/json/JSONException.java diff --git a/grammars/org/json/JSONML.java b/test/org/json/JSONML.java similarity index 100% rename from grammars/org/json/JSONML.java rename to test/org/json/JSONML.java diff --git a/grammars/org/json/JSONObject$1.class b/test/org/json/JSONObject$1.class similarity index 100% rename from grammars/org/json/JSONObject$1.class rename to test/org/json/JSONObject$1.class diff --git a/grammars/org/json/JSONObject$Null.class b/test/org/json/JSONObject$Null.class similarity index 100% rename from grammars/org/json/JSONObject$Null.class rename to test/org/json/JSONObject$Null.class diff --git a/grammars/org/json/JSONObject.class b/test/org/json/JSONObject.class similarity index 100% rename from grammars/org/json/JSONObject.class rename to test/org/json/JSONObject.class diff --git a/grammars/org/json/JSONObject.java b/test/org/json/JSONObject.java similarity index 100% rename from grammars/org/json/JSONObject.java rename to test/org/json/JSONObject.java diff --git a/grammars/org/json/JSONString.class b/test/org/json/JSONString.class similarity index 100% rename from grammars/org/json/JSONString.class rename to test/org/json/JSONString.class diff --git a/grammars/org/json/JSONString.java b/test/org/json/JSONString.java similarity index 100% rename from grammars/org/json/JSONString.java rename to test/org/json/JSONString.java diff --git a/grammars/org/json/JSONStringer.java b/test/org/json/JSONStringer.java similarity index 100% rename from grammars/org/json/JSONStringer.java rename to test/org/json/JSONStringer.java diff --git a/grammars/org/json/JSONTokener.class b/test/org/json/JSONTokener.class similarity index 100% rename from grammars/org/json/JSONTokener.class rename to test/org/json/JSONTokener.class diff --git a/grammars/org/json/JSONTokener.java b/test/org/json/JSONTokener.java similarity index 100% rename from grammars/org/json/JSONTokener.java rename to test/org/json/JSONTokener.java diff --git a/grammars/org/json/JSONWriter.java b/test/org/json/JSONWriter.java similarity index 100% rename from grammars/org/json/JSONWriter.java rename to test/org/json/JSONWriter.java diff --git a/grammars/org/json/XML.java b/test/org/json/XML.java similarity index 100% rename from grammars/org/json/XML.java rename to test/org/json/XML.java diff --git a/grammars/org/json/XMLTokener.java b/test/org/json/XMLTokener.java similarity index 100% rename from grammars/org/json/XMLTokener.java rename to test/org/json/XMLTokener.java diff --git a/grammars/test.sh b/test/test.sh similarity index 100% rename from grammars/test.sh rename to test/test.sh diff --git a/grammars/wdl.zgr b/test/wdl.zgr similarity index 100% rename from grammars/wdl.zgr rename to test/wdl.zgr diff --git a/grammars/wdl_Parser.py b/test/wdl_Parser.py similarity index 100% rename from grammars/wdl_Parser.py rename to test/wdl_Parser.py From 1e56e26d5ba08a3d89c0e584c23d39a73aebc86d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 1 Aug 2012 09:35:11 -0400 Subject: [PATCH 009/140] a bit of reorganizing --- test/Lexer.java | 71 +++++----- test/ParserMain.java | 27 +--- test/Utility.java | 58 +++++++++ test/WdlParser.java | 360 +++++++++++++++++++++++++-------------------------- 4 files changed, 273 insertions(+), 243 deletions(-) diff --git a/test/Lexer.java b/test/Lexer.java index df120c1..9f12608 100644 --- a/test/Lexer.java +++ b/test/Lexer.java @@ -13,10 +13,14 @@ private File source; private String resource; private String contents; + private int line; + private int col; SourceCode(String source, String resource) { this.contents = source; this.resource = resource; + this.line = 1; + this.col = 1; } SourceCode(File source) throws IOException { @@ -34,15 +38,39 @@ CharsetDecoder cd = cs.newDecoder(); CharBuffer cb = cd.decode(buffer); this.contents = cb.toString(); + this.resource = resource; + this.line = 1; + this.col = 1; } public void advance(int amount) { + String str = this.contents.substring(0, amount); + for ( byte b : str.getBytes() ) { + if ( b == (byte) '\n' || b == (byte) '\r' ) { + this.line++; + this.col = 1; + } else { + this.col++; + } + } this.contents = this.contents.substring(amount); } public String getString() { return this.contents; } + + public String getResource() { + return this.resource; + } + + public int getLine() { + return this.line; + } + + public int getCol() { + return this.col; + } } class LexerMatch { @@ -56,39 +84,6 @@ public String getString() { private Pattern regex; private WdlParser.TerminalId terminal; - private String base64_encode(byte[] bytes) { - int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4; - int cycle = 0, b64_index = 0; - byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); - byte[] b64 = new byte[b64_len]; - byte[] buffer = new byte[3]; - Arrays.fill(buffer, (byte) -1); - - for (byte b : bytes) { - int index = cycle % 3; - buffer[index] = b; - boolean last = (cycle == (bytes.length - 1)); - if ( index == 2 || last ) { - if ( last ) { - if ( buffer[1] == -1 ) buffer[1] = 0; - if ( buffer[2] == -1 ) buffer[2] = 0; - } - - b64[b64_index++] = alphabet[buffer[0] >> 2]; - b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)]; - b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)]; - b64[b64_index++] = alphabet[buffer[2] & 0x3f]; - - if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '='; - if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '='; - - Arrays.fill(buffer, (byte) -1); - } - cycle++; - } - return new String(b64); - } - TokenLexer(Pattern regex, WdlParser.TerminalId terminal) { this.regex = regex; this.terminal = terminal; @@ -96,16 +91,18 @@ private String base64_encode(byte[] bytes) { LexerMatch match(SourceCode source) { Matcher m = this.regex.matcher(source.getString()); + LexerMatch rval = null; if ( m.find() ) { String sourceString = m.group(); - source.advance(sourceString.length()); if (this.terminal != null) - return new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), base64_encode(sourceString.getBytes()), "file", 0, 0)); + rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol())); else - return new LexerMatch(); + rval = new LexerMatch(); + + source.advance(sourceString.length()); } - return null; + return rval; } } diff --git a/test/ParserMain.java b/test/ParserMain.java index 0161c32..b337817 100644 --- a/test/ParserMain.java +++ b/test/ParserMain.java @@ -1,31 +1,6 @@ import org.json.*; import java.io.*; -import java.nio.*; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; class ParserMain { - private static String readStdin() throws IOException { - InputStreamReader stream = new InputStreamReader(System.in, "utf-8"); - char buffer[] = new char[System.in.available()]; - try { - stream.read(buffer, 0, System.in.available()); - } finally { - stream.close(); - } - return new String(buffer); - } - private static String readFile(String path) throws IOException { - FileInputStream stream = new FileInputStream(new File(path)); - try { - FileChannel fc = stream.getChannel(); - MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); - /* Instead of using default, pass in a decoder. */ - return Charset.defaultCharset().decode(bb).toString(); - } - finally { - stream.close(); - } - } private static Parser getParser(String name) throws Exception { if (name.equals("wdl")) { return new WdlParser(); @@ -43,7 +18,7 @@ public static void main(String args[]) { Parser parser = getParser(grammar); TerminalMap terminals = parser.getTerminalMap(); TokenStream tokens = new TokenStream(terminals); - String contents = readStdin(); + String contents = Utility.readStdin(); JSONArray arr = new JSONArray(contents); for ( int i = 0; i < arr.length(); i++ ) { JSONObject token = arr.getJSONObject(i); diff --git a/test/Utility.java b/test/Utility.java index 576a77e..60bbde1 100644 --- a/test/Utility.java +++ b/test/Utility.java @@ -1,5 +1,13 @@ import java.util.Collection; import java.util.Iterator; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.nio.*; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; class Utility { public static String join(Collection s, String delimiter) { StringBuilder builder = new StringBuilder(); @@ -20,4 +28,54 @@ public static String getIndentString(int spaces) { } return sb.toString(); } + public static String base64_encode(byte[] bytes) { + int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4; + int cycle = 0, b64_index = 0; + byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); + byte[] b64 = new byte[b64_len]; + byte[] buffer = new byte[3]; + Arrays.fill(buffer, (byte) -1); + for (byte b : bytes) { + int index = cycle % 3; + buffer[index] = b; + boolean last = (cycle == (bytes.length - 1)); + if ( index == 2 || last ) { + if ( last ) { + if ( buffer[1] == -1 ) buffer[1] = 0; + if ( buffer[2] == -1 ) buffer[2] = 0; + } + b64[b64_index++] = alphabet[buffer[0] >> 2]; + b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)]; + b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)]; + b64[b64_index++] = alphabet[buffer[2] & 0x3f]; + if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '='; + if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '='; + Arrays.fill(buffer, (byte) -1); + } + cycle++; + } + return new String(b64); + } + public static String readStdin() throws IOException { + InputStreamReader stream = new InputStreamReader(System.in, "utf-8"); + char buffer[] = new char[System.in.available()]; + try { + stream.read(buffer, 0, System.in.available()); + } finally { + stream.close(); + } + return new String(buffer); + } + public static String readFile(String path) throws IOException { + FileInputStream stream = new FileInputStream(new File(path)); + try { + FileChannel fc = stream.getChannel(); + MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + /* Instead of using default, pass in a decoder. */ + return Charset.defaultCharset().decode(bb).toString(); + } + finally { + stream.close(); + } + } } diff --git a/test/WdlParser.java b/test/WdlParser.java index 5dc0eaa..4bc1812 100644 --- a/test/WdlParser.java +++ b/test/WdlParser.java @@ -7,52 +7,52 @@ private HashMap expressionParsers; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 35, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 21, -1, -1 }, - { 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1 }, - { 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 25, -1, -1, -1, -1, 25, -1, 25, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 16, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, - { 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1 }, - { -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, 40, -1 }, - { -1, -1, -1, -1, -1, 26, 26, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1 }, - { 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 31, 36, 36, -1, -1, -1, -1, 31, -1, -1, -1, -1, 31, -1 }, - { -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 7, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, 33, -1 }, - { -1, -1, -1, 11, -1, -1, -1, -1, 17, -1, 17, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1 }, + { -1, -1, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 36, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 26, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 34, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1 }, + { -1, -1, 3, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, 39, -1, -1, -1, -1, 16, -1 }, + { -1, -1, -1, -1, -1, -1, 25, -1, -1, 25, -1, -1, -1, -1, -1, 22, -1, -1 }, + { -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 14, 14, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 35, -1, -1, 35, 20, 20, -1, -1, -1, -1, 20, -1 }, + { -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, 2, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, 30, -1 }, + { -1, -1, -1, 41, 13, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId { - TERMINAL_STEP(0, "step"), + TERMINAL_LBRACE(0, "lbrace"), TERMINAL_COLON(1, "colon"), - TERMINAL_LBRACE(2, "lbrace"), + TERMINAL_STEP(2, "step"), TERMINAL_RBRACE(3, "rbrace"), - TERMINAL_STRING_LITERAL(4, "string_literal"), - TERMINAL_RPAREN(5, "rparen"), - TERMINAL_SEMI(6, "semi"), - TERMINAL_COMMAND(7, "command"), - TERMINAL_OUTPUT(8, "output"), - TERMINAL_SCATTER_GATHER(9, "scatter_gather"), - TERMINAL_ACTION(10, "action"), + TERMINAL_ACTION(4, "action"), + TERMINAL_WORKFLOW(5, "workflow"), + TERMINAL_RPAREN(6, "rparen"), + TERMINAL_LPAREN(7, "lparen"), + TERMINAL_SCATTER_GATHER(8, "scatter_gather"), + TERMINAL_SEMI(9, "semi"), + TERMINAL_STRING_LITERAL(10, "string_literal"), TERMINAL_IDENTIFIER(11, "identifier"), - TERMINAL_COMMA(12, "comma"), - TERMINAL_STRING(13, "string"), - TERMINAL_WORKFLOW(14, "workflow"), - TERMINAL_LPAREN(15, "lparen"), + TERMINAL_STRING(12, "string"), + TERMINAL_OUTPUT(13, "output"), + TERMINAL_COMMAND(14, "command"), + TERMINAL_COMMA(15, "comma"), TERMINAL_FILE(16, "file"), TERMINAL_EQUALS(17, "equals"); private final int id; @@ -118,7 +118,7 @@ private ParseTree parse_step_action_command() throws SyntaxError { if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 12) { + if (rule == 27) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("cmd", 2); tree.setAstTransformation(new AstTransformNodeCreator("CommandAction", parameters)); @@ -147,7 +147,7 @@ private ParseTree parse_workflow_body() throws SyntaxError { if (current == null) { return tree; } - if (rule == 0) { + if (rule == 33) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse__gen1(); tree.add( subtree); @@ -158,48 +158,23 @@ private ParseTree parse_workflow_body() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen1() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(20, "_gen1")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 3) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 35) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_workflow_step(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - return tree; - } - return tree; - } private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(21, "wdl_entity")); + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(20, "wdl_entity")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 5) { + if (rule == 12) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_workflow(); tree.add( subtree); return tree; } - else if (rule == 37) { + else if (rule == 36) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step(); tree.add( subtree); @@ -214,8 +189,8 @@ private ParseTree parse_workflow_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "workflow_step_output")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(21, "workflow_step_output")); tree.setList(null); if ( current != null ) { if (current.getId() == 11) { @@ -225,7 +200,7 @@ private ParseTree parse_workflow_step_output() throws SyntaxError { if (current == null) { return tree; } - if (rule == 21) { + if (rule == 23) { tree.setAstTransformation(new AstTransformSubstitution(1)); next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); tree.add(next); @@ -243,13 +218,13 @@ private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "wdl")); + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(22, "wdl")); tree.setList(null); if (current == null) { return tree; } - if (rule == 41) { + if (rule == 26) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse__gen0(); tree.add( subtree); @@ -264,13 +239,13 @@ private ParseTree parse_step_action() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "step_action")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "step_action")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 27) { + if (rule == 40) { tree.setAstTransformation(new AstTransformSubstitution(2)); next = this.tokens.expect(TerminalId.TERMINAL_ACTION.id()); tree.add(next); @@ -287,55 +262,42 @@ private ParseTree parse_step_action() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_workflow_step() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "workflow_step")); - tree.setList(null); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen1")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 3) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 42) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("input", 5); - parameters.put("step", 4); - parameters.put("name", 1); - parameters.put("output", 3); - tree.setAstTransformation(new AstTransformNodeCreator("WorkflowStep", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - subtree = this.parse_workflow_step_output(); + if (rule == 34) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_workflow_step(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - subtree = this.parse_workflow_step_input(); + subtree = this.parse__gen1(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } private ParseTree parse_workflow_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "workflow_step_input")); + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "workflow_step_input")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 32) { + if (rule == 8) { tree.setAstTransformation(new AstTransformSubstitution(1)); next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); tree.add(next); @@ -354,13 +316,13 @@ private ParseTree parse_step_action_scatter_gather() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "step_action_scatter_gather")); + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "step_action_scatter_gather")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 24) { + if (rule == 4) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("gather", 6); parameters.put("scatter", 4); @@ -389,20 +351,37 @@ private ParseTree parse_step_action_scatter_gather() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_body() throws SyntaxError { + private ParseTree parse_workflow_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "step_body")); + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "workflow_step")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 25) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen8(); + if (rule == 43) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("input", 5); + parameters.put("step", 4); + parameters.put("name", 1); + parameters.put("output", 3); + tree.setAstTransformation(new AstTransformNodeCreator("WorkflowStep", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse_workflow_step_output(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse_workflow_step_input(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -414,13 +393,13 @@ private ParseTree parse_workflow() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "workflow")); + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "workflow")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 30) { + if (rule == 31) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 3); parameters.put("name", 1); @@ -446,13 +425,13 @@ private ParseTree parse_workflow_step_output_param() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "workflow_step_output_param")); + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "workflow_step_output_param")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 15) { + if (rule == 18) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("var", 0); tree.setAstTransformation(new AstTransformNodeCreator("Output", parameters)); @@ -469,13 +448,13 @@ private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "step_output")); + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 28) { + if (rule == 6) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("parameters", 2); tree.setAstTransformation(new AstTransformNodeCreator("StepOutputParameters", parameters)); @@ -498,19 +477,19 @@ private ParseTree parse_step_body_spec() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "step_body_spec")); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "step_body_spec")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 10) { + if (rule == 15) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_output(); tree.add( subtree); return tree; } - else if (rule == 16) { + else if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_action(); tree.add( subtree); @@ -525,18 +504,18 @@ private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "_gen5")); + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "_gen5")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 13) { + if (rule == 17) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); @@ -553,8 +532,8 @@ private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "_gen0")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "_gen0")); tree.setList("nlist"); if ( current != null ) { if (current.getId() == -1) { @@ -564,7 +543,7 @@ private ParseTree parse__gen0() throws SyntaxError { if (current == null) { return tree; } - if (rule == 39) { + if (rule == 3) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_wdl_entity(); tree.add( subtree); @@ -578,21 +557,27 @@ private ParseTree parse_workflow_step_input_param() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "workflow_step_input_param")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "workflow_step_input_param")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 19) { + if (rule == 16) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + parameters.put("path", 2); + tree.setAstTransformation(new AstTransformNodeCreator("File", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); tree.add(next); return tree; } - else if (rule == 34) { + else if (rule == 32) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("val", 0); tree.setAstTransformation(new AstTransformNodeCreator("String", parameters)); @@ -600,17 +585,11 @@ else if (rule == 34) { tree.add(next); return tree; } - else if (rule == 40) { + else if (rule == 39) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("path", 2); - tree.setAstTransformation(new AstTransformNodeCreator("File", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } @@ -623,18 +602,18 @@ private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "_gen3")); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "_gen3")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6 || current.getId() == 5) { + if (current.getId() == 9 || current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 23) { + if (rule == 22) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); @@ -651,13 +630,13 @@ private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step")); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "step")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 18) { + if (rule == 21) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 6); parameters.put("name", 1); @@ -686,6 +665,27 @@ private ParseTree parse_step() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } + private ParseTree parse_step_body() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "step_body")); + tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 14) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen8(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; @@ -694,14 +694,14 @@ private ParseTree parse__gen2() throws SyntaxError { ParseTree tree = new ParseTree( new NonTerminal(38, "_gen2")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6 || current.getId() == 5) { + if (current.getId() == 9 || current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 31) { + if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_workflow_step_input_param(); tree.add( subtree); @@ -719,14 +719,14 @@ private ParseTree parse__gen4() throws SyntaxError { ParseTree tree = new ParseTree( new NonTerminal(39, "_gen4")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 14) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_workflow_step_output_param(); tree.add( subtree); @@ -746,13 +746,13 @@ private ParseTree parse_step_action_sub() throws SyntaxError { if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 7) { + if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_action_command(); tree.add( subtree); return tree; } - else if (rule == 29) { + else if (rule == 28) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_action_scatter_gather(); tree.add( subtree); @@ -773,13 +773,13 @@ private ParseTree parse_step_parameter_type() throws SyntaxError { if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 22) { + if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); tree.add(next); return tree; } - else if (rule == 33) { + else if (rule == 30) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); tree.add(next); @@ -805,7 +805,7 @@ private ParseTree parse__gen8() throws SyntaxError { if (current == null) { return tree; } - if (rule == 17) { + if (rule == 13) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_body_spec(); tree.add( subtree); @@ -823,14 +823,14 @@ private ParseTree parse__gen6() throws SyntaxError { ParseTree tree = new ParseTree( new NonTerminal(43, "_gen6")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 3) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_parameter(); tree.add( subtree); @@ -848,14 +848,14 @@ private ParseTree parse__gen7() throws SyntaxError { ParseTree tree = new ParseTree( new NonTerminal(44, "_gen7")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 4) { + if (rule == 5) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); @@ -878,7 +878,7 @@ private ParseTree parse_step_parameter() throws SyntaxError { if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 9) { + if (rule == 11) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("type", 2); parameters.put("name", 0); From 423e244167d54305bb5bfc1b3a5581a7dc067df0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sun, 5 Aug 2012 21:06:54 -0400 Subject: [PATCH 010/140] Some work on a DOT Language parser --- dot/.1.dot.swo | Bin 0 -> 16384 bytes dot/.1.dot.swp | Bin 0 -> 16384 bytes dot/.Lexer.java.swp | Bin 0 -> 16384 bytes dot/.dot.zgr.swp | Bin 0 -> 12288 bytes dot/0.dot | 1 + dot/1.dot | 2143 +++++++++++++++++++++++++++++++++++ dot/2.dot | 27 + dot/3.dot | 104 ++ dot/4.dot | 20 + dot/5.dot | 2212 +++++++++++++++++++++++++++++++++++++ dot/6.dot | 2140 +++++++++++++++++++++++++++++++++++ dot/Ast.java | 46 + dot/AstList.java | 20 + dot/AstNode.java | 5 + dot/AstTransform.java | 1 + dot/AstTransformNodeCreator.java | 24 + dot/AstTransformSubstitution.java | 12 + dot/DotParser.java | 957 ++++++++++++++++ dot/ExpressionParser.java | 3 + dot/Lexer.java | 169 +++ dot/NonTerminal.java | 17 + dot/ParseTree.java | 159 +++ dot/ParseTreeNode.java | 6 + dot/Parser.java | 4 + dot/ParserMain.java | 50 + dot/SyntaxError.java | 5 + dot/TODO | 40 + dot/Terminal.java | 51 + dot/TerminalMap.java | 6 + dot/TokenStream.java | 44 + dot/Utility.java | 81 ++ dot/dot.zgr | 28 + dot/hermes.log | 0 test/CopyNumberQC.wdl | 33 + test/CopyNumberQCAlt.wdl | 29 + test/org/json/JSONArray.class | Bin 9162 -> 0 bytes test/org/json/JSONException.class | Bin 587 -> 0 bytes test/org/json/JSONObject.class | Bin 17385 -> 0 bytes test/org/json/JSONString.class | Bin 156 -> 0 bytes test/org/json/JSONTokener.class | Bin 5033 -> 0 bytes 40 files changed, 8437 insertions(+) create mode 100644 dot/.1.dot.swo create mode 100644 dot/.1.dot.swp create mode 100644 dot/.Lexer.java.swp create mode 100644 dot/.dot.zgr.swp create mode 100644 dot/0.dot create mode 100644 dot/1.dot create mode 100644 dot/2.dot create mode 100644 dot/3.dot create mode 100644 dot/4.dot create mode 100644 dot/5.dot create mode 100644 dot/6.dot create mode 100644 dot/Ast.java create mode 100644 dot/AstList.java create mode 100644 dot/AstNode.java create mode 100644 dot/AstTransform.java create mode 100644 dot/AstTransformNodeCreator.java create mode 100644 dot/AstTransformSubstitution.java create mode 100644 dot/DotParser.java create mode 100644 dot/ExpressionParser.java create mode 100644 dot/Lexer.java create mode 100644 dot/NonTerminal.java create mode 100644 dot/ParseTree.java create mode 100644 dot/ParseTreeNode.java create mode 100644 dot/Parser.java create mode 100644 dot/ParserMain.java create mode 100644 dot/SyntaxError.java create mode 100644 dot/TODO create mode 100644 dot/Terminal.java create mode 100644 dot/TerminalMap.java create mode 100644 dot/TokenStream.java create mode 100644 dot/Utility.java create mode 100644 dot/dot.zgr create mode 100644 dot/hermes.log create mode 100644 test/CopyNumberQC.wdl create mode 100644 test/CopyNumberQCAlt.wdl delete mode 100644 test/org/json/JSONArray.class delete mode 100644 test/org/json/JSONException.class delete mode 100644 test/org/json/JSONObject.class delete mode 100644 test/org/json/JSONString.class delete mode 100644 test/org/json/JSONTokener.class diff --git a/dot/.1.dot.swo b/dot/.1.dot.swo new file mode 100644 index 0000000000000000000000000000000000000000..cfd1ad4c010379e05b4b9b95e4dca486aee557fa GIT binary patch literal 16384 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 Vj~tapR(a&8ysZ1>ymHzz{2QyhEDQhu literal 0 HcmV?d00001 diff --git a/dot/.1.dot.swp b/dot/.1.dot.swp new file mode 100644 index 0000000000000000000000000000000000000000..7898869f4d430bf13777041bf354d4ce3a31ab5d GIT binary patch literal 16384 zcmeHNZKxeb8D6!vCMGpREd@*2ZUrGGxjQqvvolRk)zYMDtu1J(5T(rS%-(zB%{hm2 zPtqoSRnZ~{1))Er^hfbWn;$A7Dn%4UqzH;ikzy64YMW|5{HR~i+SX_H?9T38uxGaV zqrx6|ayR>&cjkTGnR(xtxi<}Oc-yspvY&bQ?DD+N>>FM8ogKUPJbtO?ZRRs|%FGJp zc|X~zBG3DUiu_2`;L3D1Icl=`=E_ZaV?|HqD`Y?Zb!lSw&Jcki0xviMJ3U58SeRcL zT;jia_u&`Z(qK45V2HpFfgu7z1cnF<5f~ycL|}-(|6c^=)4=;E+r1SH+ z>cgw|vco@H@k#Z5(&3+}__%t1cZdI1hyQtpf4bBEuFApM&wo~YRM{Qs@c-!8pX%^u zJN%bA{NFqLnGXNAiod+-|Dr0O)z`egR{WI}|K1M&mx_N=#oy84|J>mp?C?)j{HU_O z@MVjKy8k~_d_8W5JNzFjz8>G(I{Y6h{y^3KcRT#=E56qMT!(+M;ty5!2hQ2*-xC#o zu;M?~;UBN~t1AA!4*yuke*4R}w*R{he_eLAMEgFI{d}wZtee(4xe@S zhdcb~4*#2qzqZoi+I{c42d^Mcj!K(e&y<%(o)$8HM z5P=~ALj;Bh3=tS2FhpR8zz~5U0x#kSDD9Pd`nMDZMg0E1KL3B=Rh~BkCct|D4m@(c z=bZ+Q0~Rv<13Zdz&S!yl0p|ff!nx}%;Cf&u@O_*EZvhSgPvemC4PXqs z5jcZ0@;yLt)_x6eKQw*&eHQizn&x)nz!649QvMB$T$oViCNfbvF0z(OHO$PG)~n;=Q8 zM=8NY&f|lU!*cRc}#I;gVx236l2GwE7v%C@G+<$8+rUn}Zc;r4jO*W51$!UhghnY_$ z!xqY6!L82TUd_N;imznSZ)zwheJ^;2fVlS}Y8 zIbmiSYC4+E);Ev&``$erua*t&Up?Vpv3SBOZ)J}^Ut8bw7j5GqpG}V8m07$wv3|;* z&CTX~W$^{QKEq$xPi80g`|nWe+MgVs`)aKHnHg&{Gul_1UUB}v6=&hE;e1@2{|{DY z;veF?ePjKe{954m00CoUB!`c5da00jr*bO{{^Zyrt4*_onE(Fft4&W=m z$ARmCi-9L_7w~o9Q@{w%|mAMkD9HsF209^fqQ1nvWF2T~vep2gk34}d#>HGl)> z0QcjL;4WYcTn=mpeu{g7yMZ}yC9n(lCGHD851azt3S0m@j5~ub1GfP01TF#|LtO3! ziuioBh|%zQ5k%m_xaAOGam%sq3Lj5pu3OxxOpni|8)mPsX0ypnYewnO7|U;QFT#rq zQdlI5?6};bJW!Svi|pfIQJmHmeU!H_4i-h_SoBer*yR>wt?A{J8mo&D(N|R;>EZ-Li`I>BDvI zHeQKhWO^xg9l<76qL`EY`Y3mNy_7qSc}sb@k6YdcFMKIyJ9pJ#*Ex6eDylPF61iFw zv#Inda@0{?UY8ckF<()eMVaGFEU%=>KB(ioDvzZL3&-eEtDHLOC~qtmeK_hUF9%Bt z;;5s%2rDd@bhWUvggA~lvC4^~^74*np~F#mXlHxqI3DFuzU(7()4|IF?!v;&D_+*J z!U8wOPPv53S_dyH;_~dnZ8hN1RYyG@+_4()GCwbLI4ZaM67HC(d08*ZJ{^P}QF&~Y$BxQlJLa+Dn8#Lm>^SDJRUSJkkF4_8QF&yQ VM~=!Pt2}a4Ue^6`UODX<{tc-yEHD57 literal 0 HcmV?d00001 diff --git a/dot/.Lexer.java.swp b/dot/.Lexer.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..19ed8d91d7b73352ba9f2d0c63af4a95e207aea1 GIT binary patch literal 16384 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 Cpg`CF literal 0 HcmV?d00001 diff --git a/dot/0.dot b/dot/0.dot new file mode 100644 index 0000000..c8f6877 --- /dev/null +++ b/dot/0.dot @@ -0,0 +1 @@ +digraph G {"Hello"->World} diff --git a/dot/1.dot b/dot/1.dot new file mode 100644 index 0000000..fff85a1 --- /dev/null +++ b/dot/1.dot @@ -0,0 +1,2143 @@ +/* this graph is from the graphviz rtest/graph directory. Laid out and rendered as + sfdp -Gsize=67! -Goverlap=prism -Tpng root.gv > root.png +*/ +digraph G_component_0 { + graph [ranksep=3, root="189E"]; + 1 [label="02f5daf56e299b8a8ecea892", shape=hexagon, style=filled, color=green]; + "189E" [label=ca5af2, shape=box, style=filled, color=blue]; + "790E" [label=b4dfef6, shape=box, style=filled, color=grey]; + 2 [label="171192dc1f8e6ea551548a910c00", shape=hexagon, style=filled, color=green]; + "191E" [label="629e42", shape=box, style=filled, color=grey]; + 3 [label="6bce02baf91781a831e1b95", shape=hexagon, style=filled, color=green]; + "193E" [label="1c08373", shape=box, style=filled, color=grey]; + 4 [label="6236a67933a619a6a3d48", shape=hexagon, style=filled, color=green]; + "195E" [label=be8f4199f, shape=box, style=filled, color=grey]; + 5 [label="50962c93b4cb293f5beb59eb", shape=hexagon, style=filled, color=green]; + "197E" [label=be8f4199f, shape=box, style=filled, color=grey]; + 6 [label="05d4b1ed6a6135eec3abd3f2", shape=hexagon, style=filled, color=green]; + "199E" [shape=box, style=filled, color=grey]; + 7 [label="08769f73d31c1a99be2d9363f", shape=hexagon, style=filled, color=green]; + "201E" [label="629e42", shape=box, style=filled, color=grey]; + 8 [label=a6a196a504c3a7657d1fa41, shape=hexagon, style=filled, color=green]; + "203E" [label=cd856f, shape=box, style=filled, color=grey]; + 9 [label="837ebf4bde22e1f1535cb662", shape=hexagon, style=filled, color=green]; + "725E" [label=d0eb84, shape=box, style=filled, color=grey]; + "785E" [label=dd2ba36, shape=box, style=filled, color=grey]; + 10 [label="5f865c374cb3fe976dd376b8", shape=hexagon, style=filled, color=green]; + "205E" [label="23ad1", shape=box, style=filled, color=grey]; + 11 [label="8be752bc95d436a90493bec9", shape=hexagon, style=filled, color=green]; + "207E" [label=ee91c97828, shape=box, style=filled, color=grey]; + 12 [label="969a58db14386cb9d2f51ec", shape=hexagon, style=filled, color=green]; + "209E" [label="7c7c", shape=box, style=filled, color=grey]; + 13 [label=da24f74aad2ff519009d1f38c, shape=hexagon, style=filled, color=green]; + "211E" [label="460aed10cc9", shape=box, style=filled, color=grey]; + 14 [label="3124d3a6ed3381a6341c6", shape=hexagon, style=filled, color=green]; + "213E" [label=bbe0a8f93dc1, shape=box, style=filled, color=grey]; + 15 [label="71512ec7d43f958f2b6da", shape=hexagon, style=filled, color=green]; + "215E" [label="3f0a2b4eb62f", shape=box, style=filled, color=grey]; + 16 [label="3828a2c682419423cf", shape=hexagon, style=filled, color=green]; + "727E" [label=2, shape=box, style=filled, color=grey]; + "784E" [shape=box, style=filled, color=grey]; + 17 [label=aa868f65c34cdb64f1fad19a, shape=hexagon, style=filled, color=green]; + "217E" [label="3089106e3b", shape=box, style=filled, color=grey]; + "787E" [label="1aaaab063", shape=box, style=filled, color=grey]; + 18 [label=dca32af03698c988b22, shape=hexagon, style=filled, color=green]; + "219E" [label=eb8, shape=box, style=filled, color=grey]; + 19 [label=d8f4a9e463a1e89217f, shape=hexagon, style=filled, color=green]; + "221E" [label="4c6c8c", shape=box, style=filled, color=grey]; + 20 [label=c96782ef56711c5d6a3f69, shape=hexagon, style=filled, color=green]; + "223E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; + 21 [label="4f04c39708f", shape=hexagon, style=filled, color=green]; + "225E" [label=a49284e9, shape=box, style=filled, color=grey]; + 22 [label="97284d4c3a5d499853f0e", shape=hexagon, style=filled, color=green]; + "227E" [label="53069e384a2", shape=box, style=filled, color=grey]; + "792E" [label="79b69c612", shape=box, style=filled, color=grey]; + 23 [label=c4d32527b670afb370d643, shape=hexagon, style=filled, color=green]; + "231E" [label=e851f5ddd920, shape=box, style=filled, color=grey]; + 24 [label="5e9156098c064", shape=hexagon, style=filled, color=green]; + "233E" [shape=box, style=filled, color=grey]; + 25 [label="3d475ea3aeca51b60212dd", shape=hexagon, style=filled, color=green]; + "235E" [label="4280833ef80172", shape=box, style=filled, color=grey]; + 26 [label="966d271c22e75c7538", shape=hexagon, style=filled, color=green]; + "237E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 27 [label=b630e1af6ae1997f0e8ba750, shape=hexagon, style=filled, color=green]; + "239E" [label=bb828f1a326, shape=box, style=filled, color=grey]; + "783E" [label="499f6985db294c", shape=box, style=filled, color=grey]; + 28 [label=ebd8ffc2ac3a90efb8af9, shape=hexagon, style=filled, color=green]; + "241E" [label="1ebeec", shape=box, style=filled, color=grey]; + "791E" [label=c0b727, shape=box, style=filled, color=grey]; + 29 [label="69fdd1a1f4768c5efe7", shape=hexagon, style=filled, color=green]; + "243E" [label="35b8742610", shape=box, style=filled, color=grey]; + 30 [label=d93a80739fc1edb41a11b7294, shape=hexagon, style=filled, color=green]; + "245E" [label=e03b8bc0435a, shape=box, style=filled, color=grey]; + 31 [label=bf65cfddeb00ff847feae0c, shape=hexagon, style=filled, color=green]; + "247E" [label="8df", shape=box, style=filled, color=grey]; + 32 [label="916c686a1e82dba72524a", shape=hexagon, style=filled, color=green]; + "249E" [label=a849f9d352e, shape=box, style=filled, color=grey]; + 33 [label=f496bcf0889b301d77819c, shape=hexagon, style=filled, color=green]; + "251E" [label=f29dfb9, shape=box, style=filled, color=grey]; + 34 [label="76889f7d35e", shape=hexagon, style=filled, color=green]; + "253E" [label=e7ef998, shape=box, style=filled, color=grey]; + 35 [label="668d636002", shape=hexagon, style=filled, color=green]; + "255E" [label="4379b5ed", shape=box, style=filled, color=grey]; + 36 [label=e1e4c23db39d8bd633c3a, shape=hexagon, style=filled, color=green]; + "257E" [label="1ed5d7f63b8c6", shape=box, style=filled, color=grey]; + 37 [label="842bc5775657c1e0d67", shape=hexagon, style=filled, color=green]; + "259E" [label=a387210a27b, shape=box, style=filled, color=grey]; + 38 [label=e4e2f4e6d, shape=hexagon, style=filled, color=green]; + "261E" [label="1f4f0fdf", shape=box, style=filled, color=grey]; + 39 [label="04390dec6f1779353c07f5", shape=hexagon, style=filled, color=green]; + "263E" [label=bac77c3f414a, shape=box, style=filled, color=grey]; + 40 [label="69f2611acc42c36ed7cc", shape=hexagon, style=filled, color=green]; + "265E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 41 [label="1562abef0d8241", shape=hexagon, style=filled, color=green]; + "267E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; + 42 [label=e49aaa5cc4e44355d6a0, shape=hexagon, style=filled, color=green]; + "269E" [label=cc3f63d, shape=box, style=filled, color=grey]; + 43 [label=e8ebe1bf5f421c1223, shape=hexagon, style=filled, color=green]; + "271E" [label="96325ea", shape=box, style=filled, color=grey]; + 44 [label="2759e82e30d6d", shape=hexagon, style=filled, color=green]; + "273E" [label=ca5af2, shape=box, style=filled, color=grey]; + 45 [label="23c1ec53358d237c1", shape=hexagon, style=filled, color=green]; + "275E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 46 [label="5838586c293d455", shape=hexagon, style=filled, color=green]; + "277E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; + 47 [label=f841118350a27b7ea29a9c9d, shape=hexagon, style=filled, color=green]; + "279E" [label="69f4ecb77d", shape=box, style=filled, color=grey]; + 48 [label="658d208447d8ec5d6de8", shape=hexagon, style=filled, color=green]; + "281E" [label=f7b22b9640, shape=box, style=filled, color=grey]; + 49 [label="11180ae7706510211bc4", shape=hexagon, style=filled, color=green]; + "283E" [label="052bb6e3", shape=box, style=filled, color=grey]; + 50 [label="5807acd8d58e006f43", shape=hexagon, style=filled, color=green]; + "285E" [shape=box, style=filled, color=grey]; + 51 [label=fe4e848cb5291ee59a2, shape=hexagon, style=filled, color=green]; + "287E" [label=e3aefac763, shape=box, style=filled, color=grey]; + 52 [label=c4f31ea3844e12da27ad47c6, shape=hexagon, style=filled, color=green]; + "289E" [label=fb16636aae, shape=box, style=filled, color=grey]; + 53 [label="00cbeb87c182ca0785f", shape=hexagon, style=filled, color=green]; + "291E" [label="3089106e3b", shape=box, style=filled, color=grey]; + 54 [label="11f088bfd8", shape=hexagon, style=filled, color=green]; + "293E" [label="6a80cbe", shape=box, style=filled, color=grey]; + 56 [label="3c2a62e0e5e9f7", shape=hexagon, style=filled, color=green]; + "295E" [label=ae32701, shape=box, style=filled, color=grey]; + 57 [label=dd84fe6a65cfac7bca03ebd, shape=hexagon, style=filled, color=green]; + "297E" [shape=box, style=filled, color=grey]; + 58 [label=b06bbfa920aa95dd, shape=hexagon, style=filled, color=green]; + "299E" [label=07, shape=box, style=filled, color=grey]; + 59 [label="6b5aaa4bdf44b2c898854", shape=hexagon, style=filled, color=green]; + "301E" [label="4c6c8c", shape=box, style=filled, color=grey]; + "789E" [label="3a0ff0", shape=box, style=filled, color=grey]; + 60 [label="855d26296eda4eb7", shape=hexagon, style=filled, color=green]; + "303E" [label="53069e384a2", shape=box, style=filled, color=grey]; + 61 [label=e82f47b8d4949ba4af69b38cbc19, shape=hexagon, style=filled, color=green]; + "305E" [label=b62cd1d0a0, shape=box, style=filled, color=grey]; + 62 [label="86569bffb49adf6b3d0ebac", shape=hexagon, style=filled, color=green]; + "307E" [label="660ffeb76fc59", shape=box, style=filled, color=grey]; + 63 [label=a96e47ff37983425a3e452095, shape=hexagon, style=filled, color=green]; + "309E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 64 [label="71a48d11b2e7e56b1df128bd", shape=hexagon, style=filled, color=green]; + "311E" [label=be8f4199f, shape=box, style=filled, color=grey]; + 65 [label=a0befe6dd1ca7b165786835, shape=hexagon, style=filled, color=green]; + "313E" [label="3cfae", shape=box, style=filled, color=grey]; + 66 [label=f33ec11db496f7bfcb024f, shape=hexagon, style=filled, color=green]; + "315E" [label="71e6b", shape=box, style=filled, color=grey]; + 67 [label=fe6be3206549f5b5564acde84783, shape=hexagon, style=filled, color=green]; + "317E" [shape=box, style=filled, color=grey]; + 68 [label=e4dba079d5fcb1f165920a3bf, shape=hexagon, style=filled, color=green]; + "319E" [shape=box, style=filled, color=grey]; + 70 [label="16c508ab98483d430bbe", shape=hexagon, style=filled, color=green]; + "321E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 71 [label="9c9e2e0f2da8758e436c", shape=hexagon, style=filled, color=green]; + "327E" [label=cd0d985a366cad7e, shape=box, style=filled, color=grey]; + 72 [label=fb039d7a2a9fe73b5f468eba9, shape=hexagon, style=filled, color=green]; + "329E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 73 [label="2ef949c4a39b", shape=hexagon, style=filled, color=green]; + "331E" [label="617809d979f", shape=box, style=filled, color=grey]; + 74 [label=a9497e0757b0969bde707ed5, shape=hexagon, style=filled, color=green]; + "333E" [label="541ab86a2e", shape=box, style=filled, color=grey]; + 75 [label="230cc6bbc66b24eae94fa03d", shape=hexagon, style=filled, color=green]; + "335E" [shape=box, style=filled, color=grey]; + 76 [label="1d163eac141def176461c", shape=hexagon, style=filled, color=green]; + "337E" [label="0acc5bb8ca4", shape=box, style=filled, color=grey]; + 77 [label="32979f8cf86", shape=hexagon, style=filled, color=green]; + "339E" [label=a7e89580, shape=box, style=filled, color=grey]; + 78 [label="37d80ae421dba4a70730338860", shape=hexagon, style=filled, color=green]; + "341E" [shape=box, style=filled, color=grey]; + 79 [label=fbba7215e7c13173a60206, shape=hexagon, style=filled, color=green]; + "343E" [label="617809d979f", shape=box, style=filled, color=grey]; + 80 [label="2dd8cc4d693415f93c0f8fc", shape=hexagon, style=filled, color=green]; + "345E" [label="94da691e20e3", shape=box, style=filled, color=grey]; + 81 [label="00880e6f50c765ebc1f85d3e9", shape=hexagon, style=filled, color=green]; + "347E" [label=e7ef998, shape=box, style=filled, color=grey]; + 82 [label=ef13d45b1277ac9a0444adb, shape=hexagon, style=filled, color=green]; + "349E" [label=a7fe7, shape=box, style=filled, color=grey]; + 83 [label="2573e1bf51f1b307f4640", shape=hexagon, style=filled, color=green]; + "351E" [label="84e4ede82074", shape=box, style=filled, color=grey]; + 84 [label="162d8039483d8", shape=hexagon, style=filled, color=green]; + "353E" [label=a8e9, shape=box, style=filled, color=grey]; + 85 [label=f490de272a7f6e4af346d40, shape=hexagon, style=filled, color=green]; + "355E" [label="460aed10cc9", shape=box, style=filled, color=grey]; + "788E" [label="391256c872", shape=box, style=filled, color=grey]; + 86 [label="678bf739c344b9ad41da1", shape=hexagon, style=filled, color=green]; + "357E" [label="396b16a892fe", shape=box, style=filled, color=grey]; + 87 [label="876d120b38b0e88817", shape=hexagon, style=filled, color=green]; + "359E" [label=e5, shape=box, style=filled, color=grey]; + 88 [label="503737b64d432c60d6ac557e0e6", shape=hexagon, style=filled, color=green]; + "361E" [label="9937ccba1469", shape=box, style=filled, color=grey]; + 89 [label=b36e0be6f67fc25286127456, shape=hexagon, style=filled, color=green]; + "363E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; + 90 [label="4cc20a0b7651e486", shape=hexagon, style=filled, color=green]; + "365E" [label=e079d2c, shape=box, style=filled, color=grey]; + 91 [label="08dade990b2282", shape=hexagon, style=filled, color=green]; + "367E" [label="45827dbdd8", shape=box, style=filled, color=grey]; + 92 [label=f8128d574c356631b8a9, shape=hexagon, style=filled, color=green]; + "369E" [shape=box, style=filled, color=grey]; + 93 [label="88a4f0337c2189c3fc7b31", shape=hexagon, style=filled, color=green]; + "729E" [label=da0d7bbcf30, shape=box, style=filled, color=grey]; + 94 [label="1b13908a9f0763c0ae54af9062080", shape=hexagon, style=filled, color=green]; + "371E" [label="8b06a67a", shape=box, style=filled, color=grey]; + 95 [label=e2a5d11499b7e, shape=hexagon, style=filled, color=green]; + "373E" [label="66abc181ac4", shape=box, style=filled, color=grey]; + 96 [label="90cc275011c2013c61eb11", shape=hexagon, style=filled, color=green]; + "375E" [shape=box, style=filled, color=grey]; + 98 [label="1927c743a0d440a5a0", shape=hexagon, style=filled, color=green]; + "377E" [label=b12441ecff15fa12c, shape=box, style=filled, color=grey]; + 99 [label="155d892827c33ed3cae3", shape=hexagon, style=filled, color=green]; + "379E" [label="71e6b", shape=box, style=filled, color=grey]; + 100 [label="9f24ba80192c339a64c0", shape=hexagon, style=filled, color=green]; + "381E" [shape=box, style=filled, color=grey]; + 101 [label="3e814305b42beb41b8c706", shape=hexagon, style=filled, color=green]; + "383E" [label="1c08373", shape=box, style=filled, color=grey]; + 102 [label=eccfe5ff0af70fe9fbec8b2360f90, shape=hexagon, style=filled, color=green]; + "385E" [label=be8f4199f, shape=box, style=filled, color=grey]; + 103 [label="8fa622d9f842c5572a545ed72982", shape=hexagon, style=filled, color=green]; + "387E" [label="4dccb", shape=box, style=filled, color=grey]; + 104 [label=ad9142a65f5eab78b4ca5e, shape=hexagon, style=filled, color=green]; + "389E" [label=f36cce089, shape=box, style=filled, color=grey]; + 105 [label="20f234fdcd0e1fc50261ce8", shape=hexagon, style=filled, color=green]; + "391E" [label="67219ef689f0146b544", shape=box, style=filled, color=grey]; + 106 [label=e06cc38155ff6781cf944d745, shape=hexagon, style=filled, color=green]; + "393E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; + 107 [label=cfdf1932665dcb4cd3c, shape=hexagon, style=filled, color=green]; + "395E" [label="964b86fc1bba0e", shape=box, style=filled, color=grey]; + 108 [label="6d4a4a5a5af91b895272c30", shape=hexagon, style=filled, color=green]; + "397E" [label=b5e86c73d1198f, shape=box, style=filled, color=grey]; + 109 [label=e0ad365c2fb444358201, shape=hexagon, style=filled, color=green]; + "399E" [label=bb5e89c8963, shape=box, style=filled, color=grey]; + 110 [label=b07bbdc8cca5985d4c4, shape=hexagon, style=filled, color=green]; + "401E" [label="50023f6f88", shape=box, style=filled, color=grey]; + 111 [label=df5dba74c75b228de48c, shape=hexagon, style=filled, color=green]; + "403E" [label="7e493ee44b28", shape=box, style=filled, color=grey]; + 112 [label="0b8694c9ef9b27b9c3d8", shape=hexagon, style=filled, color=green]; + "405E" [label="2342b759c03", shape=box, style=filled, color=grey]; + 113 [label="81e20155999fa64e0ae6fd", shape=hexagon, style=filled, color=green]; + "407E" [label="4280833ef80172", shape=box, style=filled, color=grey]; + 114 [label="3ef07ae75d29a707", shape=hexagon, style=filled, color=green]; + "409E" [label="4280833ef80172", shape=box, style=filled, color=grey]; + 115 [label="4a36db80f1ab1e97", shape=hexagon, style=filled, color=green]; + "411E" [label="460aed10cc9", shape=box, style=filled, color=grey]; + 116 [label="16da5f1301b36df4df0f", shape=hexagon, style=filled, color=green]; + "413E" [label="460aed10cc9", shape=box, style=filled, color=grey]; + 117 [label="6b3f3fa236bb90592d23a", shape=hexagon, style=filled, color=green]; + "415E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; + 118 [label=f2a57e4d4f0cec516891e3, shape=hexagon, style=filled, color=green]; + "417E" [label=bd2484, shape=box, style=filled, color=grey]; + 119 [label=deb3089920548bf1ecb23f0d, shape=hexagon, style=filled, color=green]; + "419E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; + 120 [label=bf01c8a262, shape=hexagon, style=filled, color=green]; + "421E" [label=01, shape=box, style=filled, color=grey]; + 121 [label="23dc3a52fed9c119610b5e8", shape=hexagon, style=filled, color=green]; + "423E" [label="71e6b", shape=box, style=filled, color=grey]; + 123 [label="78cc16f965adc5f712ea2372c6", shape=hexagon, style=filled, color=green]; + "425E" [label="23ad1", shape=box, style=filled, color=grey]; + 124 [label="5be631dff7b97697be7dc0a2f07f2", shape=hexagon, style=filled, color=green]; + "427E" [shape=box, style=filled, color=grey]; + "786E" [label=421, shape=box, style=filled, color=grey]; + 125 [label="48398d080dfcccced48da1980", shape=hexagon, style=filled, color=green]; + "431E" [label="866808df", shape=box, style=filled, color=grey]; + 126 [label="03716a2c341e5edaa31", shape=hexagon, style=filled, color=green]; + "433E" [label="21407f8a6d7", shape=box, style=filled, color=grey]; + 127 [label=ddfeabe456a9de5f5784, shape=hexagon, style=filled, color=green]; + "435E" [label=aac615ae78, shape=box, style=filled, color=grey]; + 128 [label=d550a7f392c787661aadd48, shape=hexagon, style=filled, color=green]; + "437E" [label=e3aefac763, shape=box, style=filled, color=grey]; + 129 [label="4c82921f4ad3f07066540", shape=hexagon, style=filled, color=green]; + "439E" [label=a7fe7, shape=box, style=filled, color=grey]; + 130 [label="0bc7f8f513e0e74b270", shape=hexagon, style=filled, color=green]; + "441E" [label=a849f9d352e, shape=box, style=filled, color=grey]; + 131 [label="3b1563a23eb9", shape=hexagon, style=filled, color=green]; + "443E" [label=a8e9, shape=box, style=filled, color=grey]; + 132 [label=be233fafa38d931d894, shape=hexagon, style=filled, color=green]; + "445E" [label=a849f9d352e, shape=box, style=filled, color=grey]; + 134 [label=e7a887d88c2318beba51, shape=hexagon, style=filled, color=green]; + "447E" [label="9d8988c0945d6", shape=box, style=filled, color=grey]; + 135 [label=be6b73bd46a7a5183e8c91a, shape=hexagon, style=filled, color=green]; + "449E" [label=ee91c97828, shape=box, style=filled, color=grey]; + "769E" [label="444189d179b5db71fe", shape=box, style=filled, color=grey]; + "770E" [label="1e1fbbe14ac24e0518", shape=box, style=filled, color=grey]; + 136 [label="644f112bb0aa452ee7040a", shape=hexagon, style=filled, color=green]; + "451E" [label="52f247fc3b", shape=box, style=filled, color=grey]; + 137 [label="010957669f3770aac", shape=hexagon, style=filled, color=green]; + "453E" [label=78, shape=box, style=filled, color=grey]; + 138 [label="0a185946ee443342b07d8e1", shape=hexagon, style=filled, color=green]; + "455E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; + 139 [label=f66fe4df3d189e69ce10c9c, shape=hexagon, style=filled, color=green]; + "457E" [label="21407f8a6d7", shape=box, style=filled, color=grey]; + 140 [label="247e407f45b353f8", shape=hexagon, style=filled, color=green]; + "459E" [shape=box, style=filled, color=grey]; + 141 [label="84907547f36d0ff7", shape=hexagon, style=filled, color=green]; + "461E" [label=e920b915087, shape=box, style=filled, color=grey]; + 142 [label="805004328dad9d315d", shape=hexagon, style=filled, color=green]; + "463E" [label="4280833ef80172", shape=box, style=filled, color=grey]; + 143 [label="4f0cbd3fbf0cb1e8c", shape=hexagon, style=filled, color=green]; + "465E" [label=403126, shape=box, style=filled, color=grey]; + 144 [label="4869e993f2bb10f", shape=hexagon, style=filled, color=green]; + "467E" [label=ff, shape=box, style=filled, color=grey]; + 145 [label="665b76844ff78fc2cf66ca2", shape=hexagon, style=filled, color=green]; + "469E" [label=af0268dddd, shape=box, style=filled, color=grey]; + 146 [label="3f16509139c7dad5163b91799", shape=hexagon, style=filled, color=green]; + "471E" [label="3089106e3b", shape=box, style=filled, color=grey]; + 147 [label="01db23a60422ba93a68611cc0", shape=hexagon, style=filled, color=green]; + "473E" [shape=box, style=filled, color=grey]; + 148 [label="46125fcc583c0f494a3a1d3", shape=hexagon, style=filled, color=green]; + "475E" [label=db6c4213a717bc, shape=box, style=filled, color=grey]; + 149 [label="731857fe189fb398e80a0594", shape=hexagon, style=filled, color=green]; + "477E" [label="3089106e3b", shape=box, style=filled, color=grey]; + 150 [label="6fb7a84e370ef70feac5cb", shape=hexagon, style=filled, color=green]; + "479E" [label="396b16a892fe", shape=box, style=filled, color=grey]; + 151 [label=e343cea291b79a2ed4e, shape=hexagon, style=filled, color=green]; + "481E" [label="88d8b220746882d", shape=box, style=filled, color=grey]; + 152 [label="5f2592b20f13356b7fc8b42", shape=hexagon, style=filled, color=green]; + "483E" [shape=box, style=filled, color=grey]; + 153 [label="275a0407e33e9b8aa9cdd051", shape=hexagon, style=filled, color=green]; + "731E" [shape=box, style=filled, color=grey]; + 155 [label="173fd00917644f0f1f3e3", shape=hexagon, style=filled, color=green]; + "485E" [label="0acc5bb8ca4", shape=box, style=filled, color=grey]; + 156 [label=c72df69b40156a3254, shape=hexagon, style=filled, color=green]; + "487E" [label=fff03efcd, shape=box, style=filled, color=grey]; + 157 [label="6c632ad9c42228bb337", shape=hexagon, style=filled, color=green]; + "489E" [label=eb8, shape=box, style=filled, color=grey]; + 158 [label=bbb13dc62adf2de2a42b6, shape=hexagon, style=filled, color=green]; + "491E" [label="69ce90c9b2", shape=box, style=filled, color=grey]; + 159 [label="6282bc21f6", shape=hexagon, style=filled, color=green]; + "495E" [label=de34214b4c258c9333ec3, shape=box, style=filled, color=grey]; + 160 [label="71cf45dd4e91bcca945137b40e", shape=hexagon, style=filled, color=green]; + "499E" [label="65fd8495", shape=box, style=filled, color=grey]; + 161 [label=a3b6df27179b175c88fa4c9cf9f, shape=hexagon, style=filled, color=green]; + "501E" [label=6577, shape=box, style=filled, color=grey]; + 162 [label="284f14a259991806654e74", shape=hexagon, style=filled, color=green]; + "503E" [label="4280833ef80172", shape=box, style=filled, color=grey]; + 163 [label=a7c99ccf6ddf6f5ebbe, shape=hexagon, style=filled, color=green]; + "505E" [label=c4fd8, shape=box, style=filled, color=grey]; + 164 [label=c32d2697e8, shape=hexagon, style=filled, color=green]; + "507E" [label="52f247fc3b", shape=box, style=filled, color=grey]; + 165 [label=d12bd75c24b110ef90cdd35d3, shape=hexagon, style=filled, color=green]; + "509E" [label=0668, shape=box, style=filled, color=grey]; + 166 [label="1c07453d584f3d14b1876fdb", shape=hexagon, style=filled, color=green]; + "511E" [label="460aed10cc9", shape=box, style=filled, color=grey]; + 167 [label=f713a8b311ffa05ce3683ad10, shape=hexagon, style=filled, color=green]; + "513E" [label="30d6138b63eb", shape=box, style=filled, color=grey]; + 168 [label="3cdc90c57243373efaba65a", shape=hexagon, style=filled, color=green]; + "515E" [label=fa2afbd869, shape=box, style=filled, color=grey]; + 169 [label=e3bdbca0e2256fffa8a59018, shape=hexagon, style=filled, color=green]; + "517E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 170 [label="75ba8d840070942eb4e737849", shape=hexagon, style=filled, color=green]; + "519E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 171 [label=fbdc3ca37406f66635c8b226e, shape=hexagon, style=filled, color=green]; + "521E" [label="8cbcf5cb5", shape=box, style=filled, color=grey]; + 172 [label="40b49a5a9bb256c7a3286e56", shape=hexagon, style=filled, color=green]; + "523E" [label=f72564578be, shape=box, style=filled, color=grey]; + 173 [label="3b2f08d52e4bca3f9ca7bbbd6", shape=hexagon, style=filled, color=green]; + "525E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 174 [label="4a38abc630c82b0c48dfbf5271", shape=hexagon, style=filled, color=green]; + "527E" [label=f0bd1521, shape=box, style=filled, color=grey]; + 175 [label="2d7b7fb6c9ad6821752651f7", shape=hexagon, style=filled, color=green]; + "529E" [label="47b2da3d", shape=box, style=filled, color=grey]; + 176 [label="910b00285f11bb90d0a15641", shape=hexagon, style=filled, color=green]; + "531E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 177 [label="24431c3eb075102f07cc2c1be", shape=hexagon, style=filled, color=green]; + "533E" [shape=box, style=filled, color=grey]; + 178 [label="07f8a9e55a16beddb3c9153b0", shape=hexagon, style=filled, color=green]; + "535E" [label="81dabfaba8", shape=box, style=filled, color=grey]; + 179 [label=c1c30f30d40c4f1f84924622f, shape=hexagon, style=filled, color=green]; + "537E" [label=c5d5be3942, shape=box, style=filled, color=grey]; + 180 [label="86276bb1e23f2c7ffcbe82a0", shape=hexagon, style=filled, color=green]; + "539E" [label="0f940646", shape=box, style=filled, color=grey]; + 181 [label=f78e145a127014eb43345a0c, shape=hexagon, style=filled, color=green]; + "541E" [label=d370c12dbc, shape=box, style=filled, color=grey]; + 182 [label=a27037332d9fa5c43bcfe94c0, shape=hexagon, style=filled, color=green]; + "543E" [label="80874aa8", shape=box, style=filled, color=grey]; + 183 [label=c29ce10bb8d19b498355aa04, shape=hexagon, style=filled, color=green]; + "545E" [label="1c08373", shape=box, style=filled, color=grey]; + 184 [label="4f8c642b53c349c687534bda35db", shape=hexagon, style=filled, color=green]; + "547E" [label="46969c4", shape=box, style=filled, color=grey]; + 185 [label="30cc206b1878485", shape=hexagon, style=filled, color=green]; + "549E" [label="23ad1", shape=box, style=filled, color=grey]; + 186 [label="5d69639a5e3bdd3d", shape=hexagon, style=filled, color=green]; + "551E" [label="6139fa6adc88d", shape=box, style=filled, color=grey]; + 187 [label=b656f0ed2202b8e46eb, shape=hexagon, style=filled, color=green]; + "553E" [label=f6e6236b48bc3, shape=box, style=filled, color=grey]; + 188 [label="3b566eaa70ed401479d43a9", shape=hexagon, style=filled, color=green]; + "555E" [label="4c6c8c", shape=box, style=filled, color=grey]; + 189 [label=d6125ef42bd9958, shape=hexagon, style=filled, color=green]; + "557E" [label="4c6c8c", shape=box, style=filled, color=grey]; + 190 [label=dd12f26f8d9bb55, shape=hexagon, style=filled, color=green]; + "559E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; + 191 [label=ea890ccca2f7c2107351, shape=hexagon, style=filled, color=green]; + "561E" [label=eb8, shape=box, style=filled, color=grey]; + 192 [label="84e4f1c582427a98d7b", shape=hexagon, style=filled, color=green]; + "563E" [label=eb8, shape=box, style=filled, color=grey]; + 193 [label=d378760b814eaecb6efe636e0efc4, shape=hexagon, style=filled, color=green]; + "565E" [label="81bcc35f82891", shape=box, style=filled, color=grey]; + 194 [label=f722890f70a32dce3baff371a, shape=hexagon, style=filled, color=green]; + "567E" [label="84e4ede82074", shape=box, style=filled, color=grey]; + 195 [label="666f11bb45c3a8dcf26e1ed79", shape=hexagon, style=filled, color=green]; + "569E" [label=c90f755c8b6612d, shape=box, style=filled, color=grey]; + 196 [label="91ecbe29a71f00ed5a3", shape=hexagon, style=filled, color=green]; + "571E" [label="0a963fef9", shape=box, style=filled, color=grey]; + 197 [label="30c3f3bf8463d3843dc57d8e98", shape=hexagon, style=filled, color=green]; + "573E" [label="3089106e3b", shape=box, style=filled, color=grey]; + 198 [label="8ea965ab6ee8dedb6c3333e9", shape=hexagon, style=filled, color=green]; + "575E" [label="84e4ede82074", shape=box, style=filled, color=grey]; + 199 [label="3eecb304bab2136a76deda", shape=hexagon, style=filled, color=green]; + "577E" [label="8df", shape=box, style=filled, color=grey]; + 200 [label=d886e4b76537a99bc71b8a9331c94, shape=hexagon, style=filled, color=green]; + "579E" [label="1172dca23", shape=box, style=filled, color=grey]; + 201 [label=dcc5d5e9d6c4e, shape=hexagon, style=filled, color=green]; + "581E" [label=a8e9, shape=box, style=filled, color=grey]; + 202 [label="8292af691429f8d9ed481ff71ffd", shape=hexagon, style=filled, color=green]; + "583E" [label="212af4", shape=box, style=filled, color=grey]; + 203 [label="12fcb26b3de00ef98719c2ca", shape=hexagon, style=filled, color=green]; + "585E" [shape=box, style=filled, color=grey]; + 204 [label=a141a557a60912051f3c135, shape=hexagon, style=filled, color=green]; + "587E" [shape=box, style=filled, color=grey]; + 206 [label=f5d636e14a6cd716362158d, shape=hexagon, style=filled, color=green]; + "589E" [label="32c958c9997", shape=box, style=filled, color=grey]; + 208 [label="52a6c2063bccd83110c32", shape=hexagon, style=filled, color=green]; + "597E" [shape=box, style=filled, color=grey]; + 209 [label="46f754ea06f070dbc023e571a876", shape=hexagon, style=filled, color=green]; + "599E" [label=ffccaa9e3, shape=box, style=filled, color=grey]; + 210 [label=c10cb9baf4dcb43e24, shape=hexagon, style=filled, color=green]; + "601E" [label=ac6e99186, shape=box, style=filled, color=grey]; + 211 [label="3dafe1619016463f521f", shape=hexagon, style=filled, color=green]; + "603E" [label=b9, shape=box, style=filled, color=grey]; + 212 [label="0f5db6ce12751ddcc64e", shape=hexagon, style=filled, color=green]; + "605E" [label=bb828f1a326, shape=box, style=filled, color=grey]; + 213 [label="34c8c8dc0f6e41c7e7b2", shape=hexagon, style=filled, color=green]; + "607E" [label="2832ed5cea6", shape=box, style=filled, color=grey]; + 214 [label="0a49c95f107c0aa57c9b5748", shape=hexagon, style=filled, color=green]; + "609E" [shape=box, style=filled, color=grey]; + 215 [label="3b4fdad8e0429d112", shape=hexagon, style=filled, color=green]; + "611E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 216 [label="17dafa5ebaafd48440e3", shape=hexagon, style=filled, color=green]; + "613E" [label=b5f038f79a3, shape=box, style=filled, color=grey]; + 217 [label=f4c69e5e212f89348122e8, shape=hexagon, style=filled, color=green]; + "615E" [label="396b16a892fe", shape=box, style=filled, color=grey]; + 218 [label="4f2e020854dfacce46a12", shape=hexagon, style=filled, color=green]; + "617E" [label=e079d2c, shape=box, style=filled, color=grey]; + 219 [label="6448451ac2ceade90715378b", shape=hexagon, style=filled, color=green]; + "619E" [shape=box, style=filled, color=grey]; + 221 [label=d7c27cc6f7b02a31eb64d, shape=hexagon, style=filled, color=green]; + "623E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; + 223 [label=eccf7c722ddf, shape=hexagon, style=filled, color=green]; + "625E" [label=df61d5f5fc, shape=box, style=filled, color=grey]; + 224 [label="86633c26be93ada8b", shape=hexagon, style=filled, color=green]; + "627E" [label="08500a6044", shape=box, style=filled, color=grey]; + 225 [label="3f9ddf1ffbc0d38b", shape=hexagon, style=filled, color=green]; + "629E" [label=07, shape=box, style=filled, color=grey]; + 226 [label=e33792703, shape=hexagon, style=filled, color=green]; + "631E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; + 227 [label="293a225dc56dd1e0564e6bb", shape=hexagon, style=filled, color=green]; + "633E" [label=e3aefac763, shape=box, style=filled, color=grey]; + 228 [label="57c77c341f94afddef07e6", shape=hexagon, style=filled, color=green]; + "635E" [label="5e80f85274", shape=box, style=filled, color=grey]; + 229 [label="3bbfc7bfdbbb1ba1bfad7517", shape=hexagon, style=filled, color=green]; + "637E" [shape=box, style=filled, color=grey]; + 230 [label=a7167d5eb5408b3839903, shape=hexagon, style=filled, color=green]; + "639E" [label="8c8b5bde6", shape=box, style=filled, color=grey]; + 231 [label="34d7bb6af4fcd8d630de72500c8", shape=hexagon, style=filled, color=green]; + "641E" [label="32fe7eee5283", shape=box, style=filled, color=grey]; + 232 [label="8e69341faa4489", shape=hexagon, style=filled, color=green]; + "643E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 233 [label="459236f07c73814faf5", shape=hexagon, style=filled, color=green]; + "645E" [label="18083a711d", shape=box, style=filled, color=grey]; + 234 [label=c71aa521578164debd0c5, shape=hexagon, style=filled, color=green]; + "647E" [label=78, shape=box, style=filled, color=grey]; + 235 [label=a5520019b8a73bc141b5fd416a, shape=hexagon, style=filled, color=green]; + "649E" [label="3219b6b71443", shape=box, style=filled, color=grey]; + 236 [label="6c89dc59ee7aaebbbd6bb64", shape=hexagon, style=filled, color=green]; + "651E" [label="8c8b5bde6", shape=box, style=filled, color=grey]; + 237 [label=a9a36ef02f, shape=hexagon, style=filled, color=green]; + "653E" [label="6a80cbe", shape=box, style=filled, color=grey]; + 238 [label="3db761b596844f133c", shape=hexagon, style=filled, color=green]; + "655E" [label=e920b915087, shape=box, style=filled, color=grey]; + 239 [label="383db224d7508ef072bea21d0", shape=hexagon, style=filled, color=green]; + "657E" [label="975fedfb64df", shape=box, style=filled, color=grey]; + 240 [label="8e307415fb435445ced7", shape=hexagon, style=filled, color=green]; + "659E" [label="21dff35936370ae5f", shape=box, style=filled, color=grey]; + 241 [label=aff6d7896e0e142bbc3e78, shape=hexagon, style=filled, color=green]; + "661E" [label=d2498, shape=box, style=filled, color=grey]; + 242 [label=e153c6e676c7369b285b4e9033a, shape=hexagon, style=filled, color=green]; + "663E" [shape=box, style=filled, color=grey]; + 243 [label=f3c4311de0e931f08c232b, shape=hexagon, style=filled, color=green]; + "665E" [label=a849f9d352e, shape=box, style=filled, color=grey]; + 244 [label="0c72a426929600000f5", shape=hexagon, style=filled, color=green]; + "667E" [label="45827dbdd8", shape=box, style=filled, color=grey]; + 245 [label="38fa61352f5086d2cb51", shape=hexagon, style=filled, color=green]; + "669E" [label=af0268dddd, shape=box, style=filled, color=grey]; + 246 [label=ad1dd724f1c3e, shape=hexagon, style=filled, color=green]; + "671E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; + 247 [label="11bb8ed3ae227d3acefc", shape=hexagon, style=filled, color=green]; + "673E" [label=eb8, shape=box, style=filled, color=grey]; + 248 [label=f2c7b3bb4d44f977d0ab8a42351, shape=hexagon, style=filled, color=green]; + "675E" [shape=box, style=filled, color=grey]; + 249 [label="51e045ca826077ae765", shape=hexagon, style=filled, color=green]; + "679E" [label=e842, shape=box, style=filled, color=grey]; + 251 [label="3b6b2c549de670d7bf5fc0ee", shape=hexagon, style=filled, color=green]; + "681E" [shape=box, style=filled, color=grey]; + 252 [label="5eea496cc301b2a9721", shape=hexagon, style=filled, color=green]; + "683E" [shape=box, style=filled, color=grey]; + 253 [label=bfc6564cbdeeffac00a141, shape=hexagon, style=filled, color=green]; + "685E" [label="3b0a8a1c2e5050bd", shape=box, style=filled, color=grey]; + 254 [label=c360aaeb167487c9578a8f, shape=hexagon, style=filled, color=green]; + "687E" [label=d, shape=box, style=filled, color=grey]; + 255 [label="39d025b265f9790490781cb201", shape=hexagon, style=filled, color=green]; + "689E" [label="5e80f85274", shape=box, style=filled, color=grey]; + 256 [label=b4ce21e0a3df1d097277d6, shape=hexagon, style=filled, color=green]; + "691E" [label=a849f9d352e, shape=box, style=filled, color=grey]; + 257 [label="8bdb6a91c6dee925b557c705b3", shape=hexagon, style=filled, color=green]; + "693E" [label="53069e384a2", shape=box, style=filled, color=grey]; + 258 [label=ac487676a04e4, shape=hexagon, style=filled, color=green]; + "695E" [label=a8e9, shape=box, style=filled, color=grey]; + 259 [label="18115fa32ff1cb99", shape=hexagon, style=filled, color=green]; + "697E" [label="45827dbdd8", shape=box, style=filled, color=grey]; + 260 [label=b7b899dc8bc6a32b28cb098fa16, shape=hexagon, style=filled, color=green]; + "699E" [label="32fe7eee5283", shape=box, style=filled, color=grey]; + 261 [label=b69e426d974e1907e88, shape=hexagon, style=filled, color=green]; + "703E" [label=e842, shape=box, style=filled, color=grey]; + 262 [label="60d0128bdb61ae40e98638bd1391", shape=hexagon, style=filled, color=green]; + "705E" [label="23ad1", shape=box, style=filled, color=grey]; + 264 [label="8fb60d769e4c387", shape=hexagon, style=filled, color=green]; + "709E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; + 265 [label=e1fa7f549e5a0893bb42da5, shape=hexagon, style=filled, color=green]; + "711E" [label="6a3c6921b0aeceda3", shape=box, style=filled, color=grey]; + 266 [label=a77622f2ff77ffeeb2, shape=hexagon, style=filled, color=green]; + "713E" [label="21dff35936370ae5f", shape=box, style=filled, color=grey]; + 267 [label="30d9d350943c0e3ff7594b50", shape=hexagon, style=filled, color=green]; + "715E" [label=b5e86c73d1198f, shape=box, style=filled, color=grey]; + 268 [label="89ced1a7906d58d687d5a04", shape=hexagon, style=filled, color=green]; + "717E" [label=c0174bbe7ae8, shape=box, style=filled, color=grey]; + 269 [label="1de26f6b12b0d292f94184", shape=hexagon, style=filled, color=green]; + "719E" [label="65fd8495", shape=box, style=filled, color=grey]; + 270 [label="26fa7360ab81be9d4434a", shape=hexagon, style=filled, color=green]; + "721E" [label=af0268dddd, shape=box, style=filled, color=grey]; + 272 [label="4a9d79c960b8d33e39251e5f66", shape=hexagon]; + "34E" [label="330342f283ef2", shape=box, style=filled, color=grey]; + "252E" [label="3dafb9a29c00", shape=box, style=filled, color=grey]; + "436E" [label="8d5137b16a", shape=box, style=filled, color=grey]; + 274 [label="10a7d61c201c67a5e78542807cd", shape=hexagon]; + "59E" [label=ef6361295eba07, shape=box, style=filled, color=grey]; + "500E" [label=a8f0fe2eb7bc1471, shape=box, style=filled, color=grey]; + "720E" [label=cfff3acd8e9d, shape=box, style=filled, color=grey]; + 275 [label=f8ff39eab120851f143bf19, shape=hexagon]; + "98E" [label="4e3cfd27a", shape=box, style=filled, color=grey]; + 278 [label="4995c71223c9f6067324d387a2", shape=hexagon]; + "35E" [label="57948adb5dead", shape=box, style=filled, color=grey]; + "488E" [label=a738ba39, shape=box, style=filled, color=grey]; + "598E" [label=be7d637c50c, shape=box, style=filled, color=grey]; + "604E" [label="8d52f183ec", shape=box, style=filled, color=grey]; + "628E" [label=cef12b6, shape=box, style=filled, color=grey]; + 279 [label=b9ae94e6935503603341ecf4, shape=hexagon]; + "99E" [label="14a3c17f3d", shape=box, style=filled, color=grey]; + 280 [label=fd28c194a46fde909b019c52f, shape=hexagon]; + "242E" [label="9fe65061641", shape=box, style=filled, color=grey]; + "270E" [label="34d06d1ed6", shape=box, style=filled, color=grey]; + "272E" [label="713db1c1", shape=box, style=filled, color=grey]; + "284E" [label="90dccb18c0", shape=box, style=filled, color=grey]; + "286E" [label=e17fea65, shape=box, style=filled, color=grey]; + "288E" [label=aebb7b91b, shape=box, style=filled, color=grey]; + "586E" [label="4348f3abcb7716", shape=box, style=filled, color=grey]; + "763E" [label=b082f7a5ff, shape=box, style=filled, color=grey]; + 281 [label="7c0ab977f5a3c4ab6d625f5033", shape=hexagon]; + "45E" [label="20949455f573f", shape=box, style=filled, color=grey]; + "470E" [label=c338481d79773, shape=box, style=filled, color=grey]; + "670E" [label=e1d01ef89f, shape=box, style=filled, color=grey]; + "722E" [label=c4507c22d19, shape=box, style=filled, color=grey]; + 282 [label="7e0b91491c8c8566892cd9a0889", shape=hexagon]; + "103E" [label=de9efa12873949, shape=box, style=filled, color=grey]; + 283 [label=d58478d9c273ad4f4b2e091324, shape=hexagon]; + "165E" [label="1a220eb692c", shape=box, style=filled, color=grey]; + 284 [label="8be0efdd94a6383e87fbfded4f", shape=hexagon]; + "39E" [label=c8a6c26d4fd9f, shape=box, style=filled, color=grey]; + "224E" [label="8cbae42a3900", shape=box, style=filled, color=grey]; + "268E" [label=fc73, shape=box, style=filled, color=grey]; + "632E" [shape=box, style=filled, color=grey]; + "710E" [label="102f1", shape=box, style=filled, color=grey]; + 285 [label="3aeb78ea51020a44f2d2615436dae", shape=hexagon]; + "53E" [label="96deede0c6b44119", shape=box, style=filled, color=grey]; + 286 [label="6bbd5b422edb8e358dcc20eecf9", shape=hexagon]; + "38E" [label="4f2de229621272", shape=box, style=filled, color=grey]; + "166E" [label=d495de0b35f6, shape=box, style=filled, color=grey]; + 288 [label="4856000a6802ddfc121ef40432297", shape=hexagon, style=filled, color="#ff0000"]; + "40E" [label="04904a458422a5b9", shape=box, style=filled, color=grey]; + "218E" [label="8cd4d", shape=box, style=filled, color=grey]; + "244E" [shape=box, style=filled, color=grey]; + "246E" [label="9be88247", shape=box, style=filled, color=grey]; + "258E" [label="4f05b", shape=box, style=filled, color=grey]; + "290E" [label="8b092", shape=box, style=filled, color=grey]; + "292E" [label=c3bbf4, shape=box, style=filled, color=grey]; + "308E" [label="6331b3f", shape=box, style=filled, color=grey]; + "318E" [shape=box, style=filled, color=grey]; + "388E" [label=3711, shape=box, style=filled, color=grey]; + "472E" [label=c5255d, shape=box, style=filled, color=grey]; + "478E" [label="5c6a2", shape=box, style=filled, color=grey]; + "566E" [label="51ec95518d1b3", shape=box, style=filled, color=grey]; + "570E" [label="82a65ed4b69", shape=box, style=filled, color=grey]; + "574E" [label="05fed5e", shape=box, style=filled, color=grey]; + "608E" [label=bf, shape=box, style=filled, color=grey]; + "614E" [label=ce, shape=box, style=filled, color=grey]; + "658E" [label="1a830d9f", shape=box, style=filled, color=grey]; + "664E" [shape=box, style=filled, color=grey]; + "682E" [shape=box, style=filled, color=grey]; + 289 [label="2e31175cbd52fcd08360fe86d20", shape=hexagon]; + "41E" [label="4ad5d68f07981a", shape=box, style=filled, color=grey]; + "636E" [label="51192117f9b4", shape=box, style=filled, color=grey]; + "642E" [label="6bf214d9e7fa5f2df", shape=box, style=filled, color=grey]; + "690E" [label="558d8534f92fddfe", shape=box, style=filled, color=grey]; + "700E" [label="6819fd5a6cdd280dd", shape=box, style=filled, color=grey]; + 290 [label="3aa0ce5efcf79bc3ecced1886e89", shape=hexagon]; + "56E" [label=ff9d64ddf49a20f, shape=box, style=filled, color=grey]; + "264E" [label="6c93f24516f01d", shape=box, style=filled, color=grey]; + "510E" [label="32b98f11f3d01d6", shape=box, style=filled, color=grey]; + "718E" [label="8f7c875500073", shape=box, style=filled, color=grey]; + 291 [label="7c1767485953d9c2", shape=hexagon]; + "66E" [label=086, shape=box, style=filled, color=grey]; + "76E" [shape=box, style=filled, color=grey]; + "610E" [label="450d3a2d49cbfd", shape=box, style=filled, color=grey]; + 292 [label="9c1305d59c37e9be9f13d7d049c", shape=hexagon]; + "73E" [label=817, shape=box, style=filled, color=grey]; + 293 [label=efe092824916a5637ee35d439589, shape=hexagon]; + "49E" [shape=box, style=filled, color=grey]; + "214E" [shape=box, style=filled, color=grey]; + "216E" [shape=box, style=filled, color=grey]; + "236E" [shape=box, style=filled, color=grey]; + "278E" [shape=box, style=filled, color=grey]; + "358E" [shape=box, style=filled, color=grey]; + "398E" [shape=box, style=filled, color=grey]; + "400E" [shape=box, style=filled, color=grey]; + "402E" [shape=box, style=filled, color=grey]; + "404E" [shape=box, style=filled, color=grey]; + "406E" [shape=box, style=filled, color=grey]; + "408E" [shape=box, style=filled, color=grey]; + "412E" [shape=box, style=filled, color=grey]; + "438E" [shape=box, style=filled, color=grey]; + "448E" [shape=box, style=filled, color=grey]; + "476E" [shape=box, style=filled, color=grey]; + "504E" [shape=box, style=filled, color=grey]; + "552E" [shape=box, style=filled, color=grey]; + "634E" [shape=box, style=filled, color=grey]; + "768E" [shape=box, style=filled, color=grey]; + 295 [label="70815f0352b43dc1562133ab6eb", shape=hexagon, style=filled, color="#A52A2A"]; + "44E" [label=ef2d4636934472, shape=box, style=filled, color=grey]; + "92E" [label="22bd92e302816", shape=box, style=filled, color=grey]; + "250E" [label="74e86", shape=box, style=filled, color=grey]; + "316E" [shape=box, style=filled, color=grey]; + "380E" [shape=box, style=filled, color=grey]; + "424E" [label=c, shape=box, style=filled, color=grey]; + "442E" [label=a5a, shape=box, style=filled, color=grey]; + "446E" [label=bce, shape=box, style=filled, color=grey]; + "454E" [shape=box, style=filled, color=grey]; + "460E" [shape=box, style=filled, color=grey]; + "462E" [shape=box, style=filled, color=grey]; + "648E" [shape=box, style=filled, color=grey]; + "656E" [label=e9, shape=box, style=filled, color=grey]; + "666E" [label=b701e7, shape=box, style=filled, color=grey]; + "692E" [label=f2e7cc, shape=box, style=filled, color=grey]; + "712E" [label="8a9eb2806b0aa", shape=box, style=filled, color=grey]; + 296 [label=e287d497450664a4c0f4efc338, shape=hexagon, style=filled, color="#ff0000"]; + "47E" [label="06eff1db45cdf", shape=box, style=filled, color=grey]; + "330E" [label=c0f34a600, shape=box, style=filled, color=grey]; + "514E" [label=bd7aca295ca, shape=box, style=filled, color=grey]; + "516E" [label="0da9135", shape=box, style=filled, color=grey]; + "518E" [label=fe821bce, shape=box, style=filled, color=grey]; + "520E" [label=e64f22a31, shape=box, style=filled, color=grey]; + "522E" [label="46e412a3", shape=box, style=filled, color=grey]; + "526E" [label="99da1f8a5", shape=box, style=filled, color=grey]; + "528E" [label="0f167280", shape=box, style=filled, color=grey]; + "530E" [label="82d201", shape=box, style=filled, color=grey]; + "532E" [label="1d529eb4", shape=box, style=filled, color=grey]; + "534E" [shape=box, style=filled, color=grey]; + "536E" [label=bf141dbce, shape=box, style=filled, color=grey]; + "538E" [label=e3fd0c7b3, shape=box, style=filled, color=grey]; + "540E" [label=c96cb3, shape=box, style=filled, color=grey]; + "542E" [label="0fabab47", shape=box, style=filled, color=grey]; + "544E" [label="1b82200", shape=box, style=filled, color=grey]; + 297 [label="2ced414a91575a48f2dd29a", shape=hexagon]; + "46E" [label="85221d5e9e", shape=box, style=filled, color=grey]; + "93E" [label="97a7eea3f", shape=box, style=filled, color=grey]; + "206E" [label="4d22e1", shape=box, style=filled, color=grey]; + "426E" [label=e65185ca, shape=box, style=filled, color=grey]; + "550E" [shape=box, style=filled, color=grey]; + "706E" [label=a9012b7bb5, shape=box, style=filled, color=grey]; + 298 [label="38f162cf917ce7298663a1f1c607", shape=hexagon]; + "36E" [label=a031c9192ae8e75, shape=box, style=filled, color=grey]; + "95E" [label="062fc905b9eb35", shape=box, style=filled, color=grey]; + "364E" [label=c8fc17180bea86, shape=box, style=filled, color=grey]; + "394E" [label="09e64744536c5e1", shape=box, style=filled, color=grey]; + "420E" [label=af4a1fac3e2076, shape=box, style=filled, color=grey]; + "456E" [label="238805e2194c3", shape=box, style=filled, color=grey]; + "624E" [label="73e6ed83012", shape=box, style=filled, color=grey]; + 299 [label="549fa15d68f0b3bee6192f888cd8", shape=hexagon]; + "48E" [label=d17f8f4eeb8e63d, shape=box, style=filled, color=grey]; + "168E" [label=cca7040e47789, shape=box, style=filled, color=grey]; + "260E" [label="47ebc3f17", shape=box, style=filled, color=grey]; + "282E" [label=cf5a6049ad, shape=box, style=filled, color=grey]; + "554E" [label="2a47a6a27", shape=box, style=filled, color=grey]; + "590E" [label=eff3468631dd4, shape=box, style=filled, color=grey]; + "767E" [label=efb52b499303115c33fd, shape=box, style=filled, color=grey]; + 300 [label="8593dcf973b110d00cecdc1e756", shape=hexagon, style=filled, color="#ff7f00"]; + "62E" [label="472a156cf2b55f", shape=box, style=filled, color=grey]; + "190E" [label=647, shape=box, style=filled, color=grey]; + "226E" [shape=box, style=filled, color=grey]; + "238E" [label="8a", shape=box, style=filled, color=grey]; + "254E" [shape=box, style=filled, color=grey]; + "256E" [shape=box, style=filled, color=grey]; + "262E" [shape=box, style=filled, color=grey]; + "266E" [label=e8b, shape=box, style=filled, color=grey]; + "274E" [shape=box, style=filled, color=grey]; + "276E" [label=f, shape=box, style=filled, color=grey]; + "294E" [shape=box, style=filled, color=grey]; + "296E" [shape=box, style=filled, color=grey]; + "310E" [label="1b34fb150", shape=box, style=filled, color=grey]; + "320E" [shape=box, style=filled, color=grey]; + "322E" [label=a7d2, shape=box, style=filled, color=grey]; + "332E" [shape=box, style=filled, color=grey]; + "340E" [shape=box, style=filled, color=grey]; + "344E" [label=f55670, shape=box, style=filled, color=grey]; + "346E" [label="1ed67841", shape=box, style=filled, color=grey]; + "348E" [label=07283, shape=box, style=filled, color=grey]; + "374E" [label="73ba1714ee", shape=box, style=filled, color=grey]; + "378E" [label=27709106, shape=box, style=filled, color=grey]; + "452E" [label="93ea0", shape=box, style=filled, color=grey]; + "508E" [shape=box, style=filled, color=grey]; + "524E" [label="1d792d81", shape=box, style=filled, color=grey]; + "612E" [label=a, shape=box, style=filled, color=grey]; + "626E" [shape=box, style=filled, color=grey]; + "638E" [shape=box, style=filled, color=grey]; + "644E" [shape=box, style=filled, color=grey]; + "654E" [shape=box, style=filled, color=grey]; + "672E" [shape=box, style=filled, color=grey]; + 302 [label="23f94655294d3ff537f2915fa", shape=hexagon]; + "797E" [shape=box, style=filled, color=grey]; + "798E" [label=a2eab7c9fa641e5f, shape=box, style=filled, color=grey]; + 303 [label=a9058241db5b6b6c25569acdf5, shape=hexagon]; + "52E" [label=b2babf3244213, shape=box, style=filled, color=grey]; + "650E" [label=b354cd9e9dbb0bfa, shape=box, style=filled, color=grey]; + 304 [label=bdbdb31bd777fb65dd6dd2d0e7, shape=hexagon]; + "50E" [label="3bec1c012b498", shape=box, style=filled, color=grey]; + "640E" [label=c54f0fc1e05, shape=box, style=filled, color=grey]; + "646E" [label="9ab6c66dc", shape=box, style=filled, color=grey]; + "652E" [label="699e3db878047", shape=box, style=filled, color=grey]; + 306 [label="1d4ea80c7194689d69f9592186", shape=hexagon]; + "55E" [label="8066f87a88f4e", shape=box, style=filled, color=grey]; + "220E" [label="3a8173d6c", shape=box, style=filled, color=grey]; + "338E" [label="24dfe1a997a", shape=box, style=filled, color=grey]; + "368E" [label="65a1", shape=box, style=filled, color=grey]; + "486E" [label="59a8b435ccd", shape=box, style=filled, color=grey]; + "490E" [label="86e9b0428", shape=box, style=filled, color=grey]; + "562E" [label="5a7a610a8a", shape=box, style=filled, color=grey]; + "564E" [label="8f143077e", shape=box, style=filled, color=grey]; + "600E" [label="6472c2861e0e0dd681", shape=box, style=filled, color=grey]; + "668E" [label=f0f45e707, shape=box, style=filled, color=grey]; + "674E" [label="95e93c4a13", shape=box, style=filled, color=grey]; + "698E" [label="33e1de", shape=box, style=filled, color=grey]; + 307 [label="7204950f6233bf9c9e1f00d4a870", shape=hexagon]; + "107E" [label=ccceeef40edda78, shape=box, style=filled, color=grey]; + 308 [label=a2c4b1d72e2da483a86ae0c62e5, shape=hexagon]; + "108E" [label=eedc819a68add6, shape=box, style=filled, color=grey]; + 309 [label=f603819d560c5603259aa05dca, shape=hexagon]; + "109E" [label=acacfc83af504, shape=box, style=filled, color=grey]; + 310 [label="2f43cba12702078b4e0d3bfdae2bc", shape=hexagon]; + "110E" [label="3c1edc8de4795936", shape=box, style=filled, color=grey]; + 311 [label="8f9cdc26798117dd3e9ee4a8770", shape=hexagon]; + "58E" [label="881d373", shape=box, style=filled, color=grey]; + "234E" [shape=box, style=filled, color=grey]; + "300E" [shape=box, style=filled, color=grey]; + "306E" [label="8c7cd9b93b1cbe48e1", shape=box, style=filled, color=grey]; + "314E" [label="616d8a7b", shape=box, style=filled, color=grey]; + "342E" [shape=box, style=filled, color=grey]; + "354E" [shape=box, style=filled, color=grey]; + "370E" [shape=box, style=filled, color=grey]; + "382E" [shape=box, style=filled, color=grey]; + "422E" [shape=box, style=filled, color=grey]; + "444E" [shape=box, style=filled, color=grey]; + "582E" [shape=box, style=filled, color=grey]; + "620E" [shape=box, style=filled, color=grey]; + "630E" [shape=box, style=filled, color=grey]; + "684E" [shape=box, style=filled, color=grey]; + "696E" [shape=box, style=filled, color=grey]; + "801E" [shape=box, style=filled, color=grey]; + 312 [label="97c9d726e27304311901a52ce", shape=hexagon, style=filled, color="#ff0000"]; + "42E" [label="1112164c2f7a", shape=box, style=filled, color=grey]; + "192E" [label="5c609b12c", shape=box, style=filled, color=grey]; + "194E" [label=00265, shape=box, style=filled, color=grey]; + "196E" [label=04767, shape=box, style=filled, color=grey]; + "198E" [label=f0d99f16, shape=box, style=filled, color=grey]; + "200E" [shape=box, style=filled, color=grey]; + "202E" [label="6e186b", shape=box, style=filled, color=grey]; + "204E" [label=d382, shape=box, style=filled, color=grey]; + "312E" [label=c6b5321a, shape=box, style=filled, color=grey]; + "336E" [shape=box, style=filled, color=grey]; + "376E" [shape=box, style=filled, color=grey]; + "384E" [label=aeb8, shape=box, style=filled, color=grey]; + "386E" [label="2e53009d4a375", shape=box, style=filled, color=grey]; + "428E" [shape=box, style=filled, color=grey]; + "474E" [shape=box, style=filled, color=grey]; + "484E" [shape=box, style=filled, color=grey]; + "546E" [label=dea1d1, shape=box, style=filled, color=grey]; + "548E" [label="5a0b4b906a", shape=box, style=filled, color=grey]; + 314 [label="1727041c622518c9dd24f7c211", shape=hexagon]; + "113E" [label="49704867bee95", shape=box, style=filled, color=grey]; + 315 [label="31f2f9aef958979f9f3532b9b", shape=hexagon, style=filled, color="#ff0000"]; + "43E" [label="47cd70f", shape=box, style=filled, color=grey]; + "240E" [label="248df40dae", shape=box, style=filled, color=grey]; + "298E" [shape=box, style=filled, color=grey]; + "334E" [label="9dd5bf47f", shape=box, style=filled, color=grey]; + "360E" [shape=box, style=filled, color=grey]; + "390E" [label="28533c", shape=box, style=filled, color=grey]; + "418E" [shape=box, style=filled, color=grey]; + "492E" [label=a4c7d0, shape=box, style=filled, color=grey]; + "502E" [label="4f6f7f", shape=box, style=filled, color=grey]; + "584E" [label="7ab64a969", shape=box, style=filled, color=grey]; + "588E" [shape=box, style=filled, color=grey]; + "602E" [label=69, shape=box, style=filled, color=grey]; + "606E" [label="67513d", shape=box, style=filled, color=grey]; + "662E" [label=cf, shape=box, style=filled, color=grey]; + 316 [label=a54092a3033f7d5e41e0a76c1, shape=hexagon]; + "51E" [label="1467f017b74e", shape=box, style=filled, color=grey]; + 317 [label="2043b477ac0393676a4309514d0", shape=hexagon]; + "116E" [label=bdec8c86db51b9, shape=box, style=filled, color=grey]; + 318 [label=ab48d1f65812bc0f8ab6941c3b5, shape=hexagon]; + "74E" [label=81, shape=box, style=filled, color=grey]; + 319 [label=ca3d67754cf62fdafbf0a1e0, shape=hexagon]; + "57E" [label="75b14f1719d", shape=box, style=filled, color=grey]; + "94E" [label="62f36ea98a", shape=box, style=filled, color=grey]; + "350E" [label=e3a76d31ca59a, shape=box, style=filled, color=grey]; + "440E" [label=b3cadc253f7, shape=box, style=filled, color=grey]; + "466E" [label=fb58e11, shape=box, style=filled, color=grey]; + "676E" [label="8606837526d81cdec", shape=box, style=filled, color=grey]; + 320 [label=a7a7f3681dad1250b01cf80bc17, shape=hexagon]; + "60E" [label="2c514b0cd8f7d3", shape=box, style=filled, color=grey]; + "366E" [label="7e494b", shape=box, style=filled, color=grey]; + "434E" [label="15d44ab97", shape=box, style=filled, color=grey]; + "458E" [label="78b2d75d00166", shape=box, style=filled, color=grey]; + "618E" [label="761e0f72f95", shape=box, style=filled, color=grey]; + 321 [label="275afb2b215b966d9fac51b96b9", shape=hexagon]; + "72E" [label=ac284d73563, shape=box, style=filled, color=grey]; + "362E" [label="7e74e1587f3a4d208", shape=box, style=filled, color=grey]; + "372E" [label=ffd1b1af3b6864078f3, shape=box, style=filled, color=grey]; + "572E" [label=b38049e00, shape=box, style=filled, color=grey]; + 322 [label=c3c93c700edc0cb4f95f03c04, shape=hexagon]; + "54E" [label="99237fce1358", shape=box, style=filled, color=grey]; + "222E" [label="3dcf8f454", shape=box, style=filled, color=grey]; + "302E" [label=c5acd20cad2, shape=box, style=filled, color=grey]; + "556E" [label="6c998bf2a5edd", shape=box, style=filled, color=grey]; + "558E" [label="4b683", shape=box, style=filled, color=grey]; + 323 [label="63a3d4fb9d38a0182be6e39e76", shape=hexagon]; + "37E" [label=bba6e6e194ccf, shape=box, style=filled, color=grey]; + "208E" [label=01938827, shape=box, style=filled, color=grey]; + "210E" [label=9, shape=box, style=filled, color=grey]; + "352E" [label="64ef1d545", shape=box, style=filled, color=grey]; + "450E" [label=b473716, shape=box, style=filled, color=grey]; + "568E" [label="7c13bf753da", shape=box, style=filled, color=grey]; + "576E" [label="4e4a79111d", shape=box, style=filled, color=grey]; + "686E" [label=af4abb0d6a99, shape=box, style=filled, color=grey]; + 324 [label="4399cf78123dedd0dfe9776104", shape=hexagon]; + "228E" [label=af9c489df53, shape=box, style=filled, color=grey]; + "248E" [label="3703059dbc5a8", shape=box, style=filled, color=grey]; + "304E" [label="8a46e6", shape=box, style=filled, color=grey]; + "468E" [label=f9d09, shape=box, style=filled, color=grey]; + "578E" [label=cd1e9af3dec2, shape=box, style=filled, color=grey]; + "660E" [label="9e650e89bb", shape=box, style=filled, color=grey]; + "688E" [label=f62b136b2171, shape=box, style=filled, color=grey]; + "694E" [label="4727c415d06bcbef", shape=box, style=filled, color=grey]; + "714E" [label="38b3b0d9", shape=box, style=filled, color=grey]; + "766E" [label=a153512d982, shape=box, style=filled, color=grey]; + 325 [label="40f253cd228f7ac2d0aee", shape=hexagon]; + "97E" [label=a3ff993, shape=box, style=filled, color=grey]; + "506E" [label="7528dd86b", shape=box, style=filled, color=grey]; + 326 [label="89a2505da6179a80202d4a6c3", shape=hexagon]; + "61E" [label="75eea05672a5", shape=box, style=filled, color=grey]; + "175E" [label="3b0c08dd2ca", shape=box, style=filled, color=grey]; + "482E" [label=a3781072b, shape=box, style=filled, color=grey]; + 328 [label="2601085bde1b2450d64509f36", shape=hexagon]; + "75E" [label="0efbd", shape=box, style=filled, color=grey]; + "580E" [label=bb92d1da1f38d52f8ff, shape=box, style=filled, color=grey]; + 329 [label="5c81103c751345d0ee0f4bd", shape=hexagon]; + "96E" [label=b23526044, shape=box, style=filled, color=grey]; + 330 [label=fcbd9ad14139718bc6fcc8b4, shape=hexagon]; + "100E" [label="73ca543bf1", shape=box, style=filled, color=grey]; + "170E" [label=c2f32e2cf9, shape=box, style=filled, color=grey]; + 333 [label="44cbb41a9cfc15497eacd294", shape=doubleoctagon, style=filled, color=yellow]; + "63E" [label="6a91", shape=box, style=filled, color=grey]; + "67E" [label=b074e, shape=box, style=filled, color=grey]; + "68E" [label=06209, shape=box, style=filled, color=grey]; + "69E" [label="58e3dcc618", shape=box, style=filled, color=grey]; + "70E" [label=eee44624da, shape=box, style=filled, color=grey]; + "71E" [label="6a91", shape=box, style=filled, color=grey]; + "802E" [label=e1e8c, shape=box, style=filled, color=grey]; + "793E" [shape=box, style=filled, color=grey]; + 334 [label=b46b0756dba915943839e90a55, shape=doubleoctagon, style=filled, color=yellow]; + "64E" [label="5fdf", shape=box, style=filled, color=grey]; + "81E" [label="3eca1f94dc181", shape=box, style=filled, color=grey]; + "82E" [label="6b1bb9b0e", shape=box, style=filled, color=grey]; + "83E" [label=a54d477232, shape=box, style=filled, color=grey]; + "84E" [label=a164d9f60fbbdd, shape=box, style=filled, color=grey]; + "85E" [label="78c8463ea", shape=box, style=filled, color=grey]; + "86E" [label=c110ba7, shape=box, style=filled, color=grey]; + "87E" [label="3b63cdc0f", shape=box, style=filled, color=grey]; + "88E" [label="6f578c5128", shape=box, style=filled, color=grey]; + "89E" [label="3e048573fd", shape=box, style=filled, color=grey]; + 336 [label="825c7994d5da13afe519861818", shape=tripleoctagon, style=filled, color="#ff0000", URL="tes hi", area=test]; + "1E" [label=f4bef37b6a94bfd00, shape=box, style=filled, color=grey]; + "2E" [label=d2647f8b6d8661d08, shape=box, style=filled, color=grey]; + "3E" [label="964cb56d8f69ff058", shape=box, style=filled, color=grey]; + "4E" [label="4f35e206816c3bd22", shape=box, style=filled, color=grey]; + "5E" [label=affb2d716803a2d3e, shape=box, style=filled, color=grey]; + "6E" [label=e4ae306d9bd669c70, shape=box, style=filled, color=grey]; + "7E" [label="4dbf4395236fb03ed", shape=box, style=filled, color=grey]; + "8E" [label="15b3ad672cd2f713a", shape=box, style=filled, color=grey]; + "9E" [label="8d6e6e0cd9b842a47", shape=box, style=filled, color=grey]; + "10E" [label="00d0dd018fe879f96", shape=box, style=filled, color=grey]; + "11E" [label=f28b78d4803c, shape=box, style=filled, color=grey]; + "12E" [label="2d886da042b5384b4", shape=box, style=filled, color=grey]; + "13E" [label="548c0081a62132b44", shape=box, style=filled, color=grey]; + "14E" [label="52126553e52385d16", shape=box, style=filled, color=grey]; + "15E" [label="9fe716e738eaea34e", shape=box, style=filled, color=grey]; + "16E" [label="5782807b5f575e0a8", shape=box, style=filled, color=grey]; + "17E" [label="792fd6f9df1fa1e33", shape=box, style=filled, color=grey]; + "18E" [label=c471b6fdbfb852661, shape=box, style=filled, color=grey]; + "19E" [label=a84844dfd0052b3b5, shape=box, style=filled, color=grey]; + "20E" [label="724dabdce9744d061", shape=box, style=filled, color=grey]; + "21E" [label="57f7fd2eecec93c8b", shape=box, style=filled, color=grey]; + "22E" [label=baba65f670ee34a88, shape=box, style=filled, color=grey]; + "23E" [label=ac34ec0f0488b17ec, shape=box, style=filled, color=grey]; + "24E" [label="51e74bec5513083bb", shape=box, style=filled, color=grey]; + "25E" [label="8e2d970b2f820ee35", shape=box, style=filled, color=grey]; + "26E" [label="19398d3cd6b9c674f", shape=box, style=filled, color=grey]; + "27E" [label="6505e29f4a11d9530", shape=box, style=filled, color=grey]; + "28E" [label=bc4824f07a9d2bba6, shape=box, style=filled, color=grey]; + "29E" [label="3acbf8a1537e4e1a1", shape=box, style=filled, color=grey]; + "30E" [label="536264e787cf70469", shape=box, style=filled, color=grey]; + "31E" [label=d, shape=box, style=filled, color=grey]; + "65E" [label=d4b2, shape=box, style=filled, color=grey]; + "119E" [label="2a9caef7", shape=box, style=filled, color=grey]; + "150E" [label="73d12", shape=box, style=filled, color=grey]; + "176E" [label="8896166adc0", shape=box, style=filled, color=grey]; + "743E" [label="9f", shape=box, style=filled, color=grey]; + "744E" [label="2e1313c", shape=box, style=filled, color=grey]; + "764E" [label=cd6, shape=box, style=filled, color=grey]; + 337 [label="8304a439f91fc90b3fe8dd35be8", shape=doubleoctagon, style=filled, color=yellow]; + "120E" [label="345d26b3f821fe", shape=box, style=filled, color=grey]; + "121E" [label="357679fea1e2f", shape=box, style=filled, color=grey]; + "122E" [label=c71043819b6a79, shape=box, style=filled, color=grey]; + "123E" [label=f9df653b86fb8df, shape=box, style=filled, color=grey]; + "124E" [label="020df871874cd", shape=box, style=filled, color=grey]; + "125E" [label="4c52fdd8e396692", shape=box, style=filled, color=grey]; + "126E" [label="8b98c3ddbe0b336", shape=box, style=filled, color=grey]; + "127E" [label=d9f4abac731a9e, shape=box, style=filled, color=grey]; + "128E" [label="50f4d9b97aefe", shape=box, style=filled, color=grey]; + "129E" [label=ea920d9f5b295119, shape=box, style=filled, color=grey]; + "130E" [label=ff5c9b242337c, shape=box, style=filled, color=grey]; + "131E" [label="4e12f7ff0918", shape=box, style=filled, color=grey]; + "132E" [label=ee3b6be71d59b, shape=box, style=filled, color=grey]; + "133E" [label="615cd6b5e3d21c", shape=box, style=filled, color=grey]; + "134E" [label="6d52dd1b198bb", shape=box, style=filled, color=grey]; + "135E" [label="8c932e1e502dca", shape=box, style=filled, color=grey]; + "136E" [label=e84330eef281284a, shape=box, style=filled, color=grey]; + "137E" [label="85fc23f1c88b4", shape=box, style=filled, color=grey]; + "138E" [label="5997cb0c083422", shape=box, style=filled, color=grey]; + 339 [label=b1ffbabb24d71f67d1e0ce23c51, shape=doubleoctagon, style=filled, color=yellow]; + "151E" [shape=box, style=filled, color=grey]; + "153E" [label="41a8b095c7fd3", shape=box, style=filled, color=grey]; + "154E" [label="151bcc2a8de7ea634", shape=box, style=filled, color=grey]; + "155E" [label="6c541cad8de1b15", shape=box, style=filled, color=grey]; + "156E" [label=c935c7f4d1090ac, shape=box, style=filled, color=grey]; + "157E" [label="5ce1fcfb042b", shape=box, style=filled, color=grey]; + "158E" [label=531806429433, shape=box, style=filled, color=grey]; + "159E" [label=d285240b89cb, shape=box, style=filled, color=grey]; + "160E" [label=f22c27c0f0a54e, shape=box, style=filled, color=grey]; + "161E" [label="8d0d8314d211d80", shape=box, style=filled, color=grey]; + "162E" [shape=box, style=filled, color=grey]; + 347 [label="9652ab8b55fdb2a36d1f3fe020", shape=hexagon]; + "139E" [label=ef8b68bb5772f3, shape=box, style=filled, color=grey]; + "795E" [label="16c3ae29c0bc713", shape=box, style=filled, color=grey]; + 348 [label="676bbe7d1c1fb71742df534ce8", shape=hexagon]; + "799E" [label=a78eb40ae56aaa9, shape=box, style=filled, color=grey]; + "800E" [label="6aae8d25951", shape=box, style=filled, color=grey]; + 349 [label="66c0220688a999aaf7f1702d1", shape=hexagon]; + "141E" [label="67b6a4dca3a6d", shape=box, style=filled, color=grey]; + 350 [label="1322fb0818783e6f9a4f173d47c52", shape=hexagon]; + "142E" [label="9696c0950295d8cb5", shape=box, style=filled, color=grey]; + "678E" [label=b5c747cc9, shape=box, style=filled, color=grey]; + 351 [label=ff07977fca5513098d220d1eb3a, shape=hexagon]; + "143E" [label="89a36b13f8c344b", shape=box, style=filled, color=grey]; + "232E" [label="56292d076643", shape=box, style=filled, color=grey]; + "680E" [label=b5c747cc9, shape=box, style=filled, color=grey]; + "704E" [label="431430c49", shape=box, style=filled, color=grey]; + 352 [label=a97ef281eafc34b1630d450a1df, shape=hexagon]; + "144E" [label="4ff4e275c710c3b", shape=box, style=filled, color=grey]; + "432E" [label=d13da6273c9b4da, shape=box, style=filled, color=grey]; + 353 [label="72cbb37db85ed3c6eda5dcf8", shape=hexagon]; + "145E" [label="33ff9e43d5ab", shape=box, style=filled, color=grey]; + 354 [label="0f6784e49852c0be0da23b16", shape=hexagon]; + "146E" [label=d4f958b03a98, shape=box, style=filled, color=grey]; + "396E" [label="8e24e9b4e", shape=box, style=filled, color=grey]; + 355 [label="383f5c65cc6c25aa0a0e6dbb", shape=hexagon]; + "147E" [label="1ff8ff951ee9", shape=box, style=filled, color=grey]; + 356 [label=f52a45620969f0df4e6ae1dcd7, shape=hexagon]; + "148E" [label="5256925081c812", shape=box, style=filled, color=grey]; + 357 [label="1f5df34ad75a55a76ef4afa0a47", shape=hexagon]; + "149E" [label="26a185dde9a93dd", shape=box, style=filled, color=grey]; + 358 [label="45ba4d4c61c9601a26d59e47e0260", shape=hexagon]; + "167E" [label="99bd3e7feeb710", shape=box, style=filled, color=grey]; + 359 [label=f95344b0ae31693f3a2746597d4, shape=hexagon]; + "169E" [label="4e8259973f1f", shape=box, style=filled, color=grey]; + 360 [label=b79798b186d6b82288e8be4017d, shape=hexagon]; + "171E" [label="63b079bd5847", shape=box, style=filled, color=grey]; + 361 [label="47e0067f4d853afd2012f04daa8", shape=hexagon]; + "172E" [label="92fb5d4a0805", shape=box, style=filled, color=grey]; + 362 [label=f2b6201774de40a29b504b1f716, shape=hexagon]; + "173E" [label=d7203571944b, shape=box, style=filled, color=grey]; + 363 [label="800422ab81d804eef3e7b91dfba91", shape=hexagon]; + "174E" [label="952316a1a5a785", shape=box, style=filled, color=grey]; + 364 [label="35b941379e1af658078cffb83a2", shape=hexagon]; + "101E" [label="331675c046693f", shape=box, style=filled, color=grey]; + 365 [label=d4f7b7fba7afcf7a72397353ec, shape=hexagon]; + "102E" [label="32c4684b55361", shape=box, style=filled, color=grey]; + 367 [label=e4b45b7a2f884d3734bfd5985656, shape=hexagon]; + "104E" [label="1333074979f2d0b", shape=box, style=filled, color=grey]; + 368 [label="02c2ba83680ab57f236a33d702", shape=hexagon]; + "105E" [label="084d4bfa5853e", shape=box, style=filled, color=grey]; + 369 [label="9ccd974150a18260b207b6584caa", shape=hexagon]; + "106E" [label="28f7bfc40c88e6a", shape=box, style=filled, color=grey]; + 374 [label="653ae44d45dcadeb481b53027d", shape=hexagon]; + "111E" [label="8f95518f48528", shape=box, style=filled, color=grey]; + 375 [label=d66f542ef1ce4d02c59bec65e, shape=hexagon]; + "112E" [label="2ef209509e2a", shape=box, style=filled, color=grey]; + 377 [label=a2984b7a11e49440420058c1d80, shape=hexagon]; + "114E" [label=ef42184297591d, shape=box, style=filled, color=grey]; + 378 [label="31055116421c96b37f72a262bb", shape=hexagon]; + "115E" [label=be9c5958196ed, shape=box, style=filled, color=grey]; + 380 [label="8462bb2eec1a62d19a15865e57c92", shape=hexagon]; + "117E" [label="16a795a1d63f30df", shape=box, style=filled, color=grey]; + "392E" [label="85a34bc9616ff", shape=box, style=filled, color=grey]; + 381 [label=c21eb96fe100a1efaa128181b7, shape=hexagon]; + "118E" [label=f1b0d754353a6, shape=box, style=filled, color=grey]; + 382 [label=e3e284d0cc803d98d674f9c3f6d, shape=doubleoctagon, style=filled, color=yellow]; + "177E" [label="30417faf916", shape=box, style=filled, color=grey]; + "178E" [label=e618df70814a, shape=box, style=filled, color=grey]; + "179E" [label=fa90ddf10bd574, shape=box, style=filled, color=grey]; + "180E" [label="815cc0b83d733", shape=box, style=filled, color=grey]; + "181E" [label=f787d827958c, shape=box, style=filled, color=grey]; + "182E" [label=f20f7f513e, shape=box, style=filled, color=grey]; + "183E" [label="290907417e13", shape=box, style=filled, color=grey]; + "184E" [label=e8386a8e1c8a, shape=box, style=filled, color=grey]; + "185E" [label="319bc900218b", shape=box, style=filled, color=grey]; + "186E" [label="3ba7afb0e48ae1", shape=box, style=filled, color=grey]; + "187E" [label="6ba0776fc8e", shape=box, style=filled, color=grey]; + "188E" [label="09847696ae", shape=box, style=filled, color=grey]; + 383 [label="908f9ad506eae9ab6ada185e3", shape=doubleoctagon, style=filled, color=yellow]; + "730E" [label="65694ca6d575", shape=box, style=filled, color=grey]; + "732E" [label="37f57e81ebed95", shape=box, style=filled, color=grey]; + "741E" [label="9b6c", shape=box, style=filled, color=grey]; + "765E" [label="88ebe2e8782c", shape=box, style=filled, color=grey]; + "796E" [label="901b2105a902ee7791", shape=box, style=filled, color=grey]; + 384 [label="593caebf2037317648bb451aa79", shape=doubleoctagon, style=filled, color=yellow]; + "726E" [label="351dd0aefe480c", shape=box, style=filled, color=grey]; + "728E" [label="56e1a896", shape=box, style=filled, color=grey]; + "742E" [label="5ba4693031", shape=box, style=filled, color=grey]; + 1 -> "189E" [label=" ", color=blue, arrowhead=dot]; + 1 -> "790E" [label=" ", color=blue, arrowhead=dot]; + 2 -> "191E" [label=" ", color=blue, arrowhead=dot]; + 3 -> "193E" [label=" ", color=blue, arrowhead=dot]; + 4 -> "195E" [label=" ", color=blue, arrowhead=dot]; + 5 -> "197E" [label=" ", color=blue, arrowhead=dot]; + 6 -> "199E" [label=" ", color=blue, arrowhead=dot]; + 7 -> "201E" [label=" ", color=blue, arrowhead=dot]; + 8 -> "203E" [label=" ", color=blue, arrowhead=dot]; + 9 -> "725E" [label=" ", color=blue, arrowhead=dot]; + 9 -> "785E" [label=" ", color=blue, arrowhead=dot]; + 10 -> "205E" [label=" ", color=blue, arrowhead=dot]; + 11 -> "207E" [label=" ", color=blue, arrowhead=dot]; + 12 -> "209E" [label=" ", color=blue, arrowhead=dot]; + 13 -> "211E" [label=" ", color=blue, arrowhead=dot]; + 14 -> "213E" [label=" ", color=blue, arrowhead=dot]; + 15 -> "215E" [label=" ", color=blue, arrowhead=dot]; + 16 -> "727E" [label=" ", color=blue, arrowhead=dot]; + 16 -> "784E" [label=" ", color=blue, arrowhead=dot]; + 17 -> "217E" [label=" ", color=blue, arrowhead=dot]; + 17 -> "787E" [label=" ", color=blue, arrowhead=dot]; + 18 -> "219E" [label=" ", color=blue, arrowhead=dot]; + 19 -> "221E" [label=" ", color=blue, arrowhead=dot]; + 20 -> "223E" [label=" ", color=blue, arrowhead=dot]; + 21 -> "225E" [label=" ", color=blue, arrowhead=dot]; + 22 -> "227E" [label=" ", color=blue, arrowhead=dot]; + 22 -> "792E" [label=" ", color=blue, arrowhead=dot]; + 23 -> "231E" [label=" ", color=blue, arrowhead=dot]; + 24 -> "233E" [label=" ", color=blue, arrowhead=dot]; + 25 -> "235E" [label=" ", color=blue, arrowhead=dot]; + 26 -> "237E" [label=" ", color=blue, arrowhead=dot]; + 27 -> "239E" [label=" ", color=blue, arrowhead=dot]; + 27 -> "783E" [label=" ", color=blue, arrowhead=dot]; + 28 -> "241E" [label=" ", color=blue, arrowhead=dot]; + 28 -> "791E" [label=" ", color=blue, arrowhead=dot]; + 29 -> "243E" [label=" ", color=blue, arrowhead=dot]; + 30 -> "245E" [label=" ", color=blue, arrowhead=dot]; + 31 -> "247E" [label=" ", color=blue, arrowhead=dot]; + 32 -> "249E" [label=" ", color=blue, arrowhead=dot]; + 33 -> "251E" [label=" ", color=blue, arrowhead=dot]; + 34 -> "253E" [label=" ", color=blue, arrowhead=dot]; + 35 -> "255E" [label=" ", color=blue, arrowhead=dot]; + 36 -> "257E" [label=" ", color=blue, arrowhead=dot]; + 37 -> "259E" [label=" ", color=blue, arrowhead=dot]; + 38 -> "261E" [label=" ", color=blue, arrowhead=dot]; + 39 -> "263E" [label=" ", color=blue, arrowhead=dot]; + 40 -> "265E" [label=" ", color=blue, arrowhead=dot]; + 41 -> "267E" [label=" ", color=blue, arrowhead=dot]; + 42 -> "269E" [label=" ", color=blue, arrowhead=dot]; + 43 -> "271E" [label=" ", color=blue, arrowhead=dot]; + 44 -> "273E" [label=" ", color=blue, arrowhead=dot]; + 45 -> "275E" [label=" ", color=blue, arrowhead=dot]; + 46 -> "277E" [label=" ", color=blue, arrowhead=dot]; + 47 -> "279E" [label=" ", color=blue, arrowhead=dot]; + 48 -> "281E" [label=" ", color=blue, arrowhead=dot]; + 49 -> "283E" [label=" ", color=blue, arrowhead=dot]; + 50 -> "285E" [label=" ", color=blue, arrowhead=dot]; + 51 -> "287E" [label=" ", color=blue, arrowhead=dot]; + 52 -> "289E" [label=" ", color=blue, arrowhead=dot]; + 53 -> "291E" [label=" ", color=blue, arrowhead=dot]; + 54 -> "293E" [label=" ", color=blue, arrowhead=dot]; + 56 -> "295E" [label=" ", color=blue, arrowhead=dot]; + 57 -> "297E" [label=" ", color=blue, arrowhead=dot]; + 58 -> "299E" [label=" ", color=blue, arrowhead=dot]; + 59 -> "301E" [label=" ", color=blue, arrowhead=dot]; + 59 -> "789E" [label=" ", color=blue, arrowhead=dot]; + 60 -> "303E" [label=" ", color=blue, arrowhead=dot]; + 61 -> "305E" [label=" ", color=blue, arrowhead=dot]; + 62 -> "307E" [label=" ", color=blue, arrowhead=dot]; + 63 -> "309E" [label=" ", color=blue, arrowhead=dot]; + 64 -> "311E" [label=" ", color=blue, arrowhead=dot]; + 65 -> "313E" [label=" ", color=blue, arrowhead=dot]; + 66 -> "315E" [label=" ", color=blue, arrowhead=dot]; + 67 -> "317E" [label=" ", color=blue, arrowhead=dot]; + 68 -> "319E" [label=" ", color=blue, arrowhead=dot]; + 70 -> "321E" [label=" ", color=blue, arrowhead=dot]; + 71 -> "327E" [label=" ", color=blue, arrowhead=dot]; + 72 -> "329E" [label=" ", color=blue, arrowhead=dot]; + 73 -> "331E" [label=" ", color=blue, arrowhead=dot]; + 74 -> "333E" [label=" ", color=blue, arrowhead=dot]; + 75 -> "335E" [label=" ", color=blue, arrowhead=dot]; + 76 -> "337E" [label=" ", color=blue, arrowhead=dot]; + 77 -> "339E" [label=" ", color=blue, arrowhead=dot]; + 78 -> "341E" [label=" ", color=blue, arrowhead=dot]; + 79 -> "343E" [label=" ", color=blue, arrowhead=dot]; + 80 -> "345E" [label=" ", color=blue, arrowhead=dot]; + 81 -> "347E" [label=" ", color=blue, arrowhead=dot]; + 82 -> "349E" [label=" ", color=blue, arrowhead=dot]; + 83 -> "351E" [label=" ", color=blue, arrowhead=dot]; + 84 -> "353E" [label=" ", color=blue, arrowhead=dot]; + 85 -> "355E" [label=" ", color=blue, arrowhead=dot]; + 85 -> "788E" [label=" ", color=blue, arrowhead=dot]; + 86 -> "357E" [label=" ", color=blue, arrowhead=dot]; + 87 -> "359E" [label=" ", color=blue, arrowhead=dot]; + 88 -> "361E" [label=" ", color=blue, arrowhead=dot]; + 89 -> "363E" [label=" ", color=blue, arrowhead=dot]; + 90 -> "365E" [label=" ", color=blue, arrowhead=dot]; + 91 -> "367E" [label=" ", color=blue, arrowhead=dot]; + 92 -> "369E" [label=" ", color=blue, arrowhead=dot]; + 93 -> "729E" [label=" ", color=blue, arrowhead=dot]; + 94 -> "371E" [label=" ", color=blue, arrowhead=dot]; + 95 -> "373E" [label=" ", color=blue, arrowhead=dot]; + 96 -> "375E" [label=" ", color=blue, arrowhead=dot]; + 98 -> "377E" [label=" ", color=blue, arrowhead=dot]; + 99 -> "379E" [label=" ", color=blue, arrowhead=dot]; + 100 -> "381E" [label=" ", color=blue, arrowhead=dot]; + 101 -> "383E" [label=" ", color=blue, arrowhead=dot]; + 102 -> "385E" [label=" ", color=blue, arrowhead=dot]; + 103 -> "387E" [label=" ", color=blue, arrowhead=dot]; + 104 -> "389E" [label=" ", color=blue, arrowhead=dot]; + 105 -> "391E" [label=" ", color=blue, arrowhead=dot]; + 106 -> "393E" [label=" ", color=blue, arrowhead=dot]; + 107 -> "395E" [label=" ", color=blue, arrowhead=dot]; + 108 -> "397E" [label=" ", color=blue, arrowhead=dot]; + 109 -> "399E" [label=" ", color=blue, arrowhead=dot]; + 110 -> "401E" [label=" ", color=blue, arrowhead=dot]; + 111 -> "403E" [label=" ", color=blue, arrowhead=dot]; + 112 -> "405E" [label=" ", color=blue, arrowhead=dot]; + 113 -> "407E" [label=" ", color=blue, arrowhead=dot]; + 114 -> "409E" [label=" ", color=blue, arrowhead=dot]; + 115 -> "411E" [label=" ", color=blue, arrowhead=dot]; + 116 -> "413E" [label=" ", color=blue, arrowhead=dot]; + 117 -> "415E" [label=" ", color=blue, arrowhead=dot]; + 118 -> "417E" [label=" ", color=blue, arrowhead=dot]; + 119 -> "419E" [label=" ", color=blue, arrowhead=dot]; + 120 -> "421E" [label=" ", color=blue, arrowhead=dot]; + 121 -> "423E" [label=" ", color=blue, arrowhead=dot]; + 123 -> "425E" [label=" ", color=blue, arrowhead=dot]; + 124 -> "427E" [label=" ", color=blue, arrowhead=dot]; + 124 -> "786E" [label=" ", color=blue, arrowhead=dot]; + 125 -> "431E" [label=" ", color=blue, arrowhead=dot]; + 126 -> "433E" [label=" ", color=blue, arrowhead=dot]; + 127 -> "435E" [label=" ", color=blue, arrowhead=dot]; + 128 -> "437E" [label=" ", color=blue, arrowhead=dot]; + 129 -> "439E" [label=" ", color=blue, arrowhead=dot]; + 130 -> "441E" [label=" ", color=blue, arrowhead=dot]; + 131 -> "443E" [label=" ", color=blue, arrowhead=dot]; + 132 -> "445E" [label=" ", color=blue, arrowhead=dot]; + 134 -> "447E" [label=" ", color=blue, arrowhead=dot]; + 135 -> "449E" [label=" ", color=blue, arrowhead=dot]; + 135 -> "769E" [label=" ", color=blue, arrowhead=dot]; + 135 -> "770E" [label=" ", color=blue, arrowhead=dot]; + 136 -> "451E" [label=" ", color=blue, arrowhead=dot]; + 137 -> "453E" [label=" ", color=blue, arrowhead=dot]; + 138 -> "455E" [label=" ", color=blue, arrowhead=dot]; + 139 -> "457E" [label=" ", color=blue, arrowhead=dot]; + 140 -> "459E" [label=" ", color=blue, arrowhead=dot]; + 141 -> "461E" [label=" ", color=blue, arrowhead=dot]; + 142 -> "463E" [label=" ", color=blue, arrowhead=dot]; + 143 -> "465E" [label=" ", color=blue, arrowhead=dot]; + 144 -> "467E" [label=" ", color=blue, arrowhead=dot]; + 145 -> "469E" [label=" ", color=blue, arrowhead=dot]; + 146 -> "471E" [label=" ", color=blue, arrowhead=dot]; + 147 -> "473E" [label=" ", color=blue, arrowhead=dot]; + 148 -> "475E" [label=" ", color=blue, arrowhead=dot]; + 149 -> "477E" [label=" ", color=blue, arrowhead=dot]; + 150 -> "479E" [label=" ", color=blue, arrowhead=dot]; + 151 -> "481E" [label=" ", color=blue, arrowhead=dot]; + 152 -> "483E" [label=" ", color=blue, arrowhead=dot]; + 153 -> "731E" [label=" ", color=blue, arrowhead=dot]; + 155 -> "485E" [label=" ", color=blue, arrowhead=dot]; + 156 -> "487E" [label=" ", color=blue, arrowhead=dot]; + 157 -> "489E" [label=" ", color=blue, arrowhead=dot]; + 158 -> "491E" [label=" ", color=blue, arrowhead=dot]; + 159 -> "495E" [label=" ", color=blue, arrowhead=dot]; + 160 -> "499E" [label=" ", color=blue, arrowhead=dot]; + 161 -> "501E" [label=" ", color=blue, arrowhead=dot]; + 162 -> "503E" [label=" ", color=blue, arrowhead=dot]; + 163 -> "505E" [label=" ", color=blue, arrowhead=dot]; + 164 -> "507E" [label=" ", color=blue, arrowhead=dot]; + 165 -> "509E" [label=" ", color=blue, arrowhead=dot]; + 166 -> "511E" [label=" ", color=blue, arrowhead=dot]; + 167 -> "513E" [label=" ", color=blue, arrowhead=dot]; + 168 -> "515E" [label=" ", color=blue, arrowhead=dot]; + 169 -> "517E" [label=" ", color=blue, arrowhead=dot]; + 170 -> "519E" [label=" ", color=blue, arrowhead=dot]; + 171 -> "521E" [label=" ", color=blue, arrowhead=dot]; + 172 -> "523E" [label=" ", color=blue, arrowhead=dot]; + 173 -> "525E" [label=" ", color=blue, arrowhead=dot]; + 174 -> "527E" [label=" ", color=blue, arrowhead=dot]; + 175 -> "529E" [label=" ", color=blue, arrowhead=dot]; + 176 -> "531E" [label=" ", color=blue, arrowhead=dot]; + 177 -> "533E" [label=" ", color=blue, arrowhead=dot]; + 178 -> "535E" [label=" ", color=blue, arrowhead=dot]; + 179 -> "537E" [label=" ", color=blue, arrowhead=dot]; + 180 -> "539E" [label=" ", color=blue, arrowhead=dot]; + 181 -> "541E" [label=" ", color=blue, arrowhead=dot]; + 182 -> "543E" [label=" ", color=blue, arrowhead=dot]; + 183 -> "545E" [label=" ", color=blue, arrowhead=dot]; + 184 -> "547E" [label=" ", color=blue, arrowhead=dot]; + 185 -> "549E" [label=" ", color=blue, arrowhead=dot]; + 186 -> "551E" [label=" ", color=blue, arrowhead=dot]; + 187 -> "553E" [label=" ", color=blue, arrowhead=dot]; + 188 -> "555E" [label=" ", color=blue, arrowhead=dot]; + 189 -> "557E" [label=" ", color=blue, arrowhead=dot]; + 190 -> "559E" [label=" ", color=blue, arrowhead=dot]; + 191 -> "561E" [label=" ", color=blue, arrowhead=dot]; + 192 -> "563E" [label=" ", color=blue, arrowhead=dot]; + 193 -> "565E" [label=" ", color=blue, arrowhead=dot]; + 194 -> "567E" [label=" ", color=blue, arrowhead=dot]; + 195 -> "569E" [label=" ", color=blue, arrowhead=dot]; + 196 -> "571E" [label=" ", color=blue, arrowhead=dot]; + 197 -> "573E" [label=" ", color=blue, arrowhead=dot]; + 198 -> "575E" [label=" ", color=blue, arrowhead=dot]; + 199 -> "577E" [label=" ", color=blue, arrowhead=dot]; + 200 -> "579E" [label=" ", color=blue, arrowhead=dot]; + 201 -> "581E" [label=" ", color=blue, arrowhead=dot]; + 202 -> "583E" [label=" ", color=blue, arrowhead=dot]; + 203 -> "585E" [label=" ", color=blue, arrowhead=dot]; + 204 -> "587E" [label=" ", color=blue, arrowhead=dot]; + 206 -> "589E" [label=" ", color=blue, arrowhead=dot]; + 208 -> "597E" [label=" ", color=blue, arrowhead=dot]; + 209 -> "599E" [label=" ", color=blue, arrowhead=dot]; + 210 -> "601E" [label=" ", color=blue, arrowhead=dot]; + 211 -> "603E" [label=" ", color=blue, arrowhead=dot]; + 212 -> "605E" [label=" ", color=blue, arrowhead=dot]; + 213 -> "607E" [label=" ", color=blue, arrowhead=dot]; + 214 -> "609E" [label=" ", color=blue, arrowhead=dot]; + 215 -> "611E" [label=" ", color=blue, arrowhead=dot]; + 216 -> "613E" [label=" ", color=blue, arrowhead=dot]; + 217 -> "615E" [label=" ", color=blue, arrowhead=dot]; + 218 -> "617E" [label=" ", color=blue, arrowhead=dot]; + 219 -> "619E" [label=" ", color=blue, arrowhead=dot]; + 221 -> "623E" [label=" ", color=blue, arrowhead=dot]; + 223 -> "625E" [label=" ", color=blue, arrowhead=dot]; + 224 -> "627E" [label=" ", color=blue, arrowhead=dot]; + 225 -> "629E" [label=" ", color=blue, arrowhead=dot]; + 226 -> "631E" [label=" ", color=blue, arrowhead=dot]; + 227 -> "633E" [label=" ", color=blue, arrowhead=dot]; + 228 -> "635E" [label=" ", color=blue, arrowhead=dot]; + 229 -> "637E" [label=" ", color=blue, arrowhead=dot]; + 230 -> "639E" [label=" ", color=blue, arrowhead=dot]; + 231 -> "641E" [label=" ", color=blue, arrowhead=dot]; + 232 -> "643E" [label=" ", color=blue, arrowhead=dot]; + 233 -> "645E" [label=" ", color=blue, arrowhead=dot]; + 234 -> "647E" [label=" ", color=blue, arrowhead=dot]; + 235 -> "649E" [label=" ", color=blue, arrowhead=dot]; + 236 -> "651E" [label=" ", color=blue, arrowhead=dot]; + 237 -> "653E" [label=" ", color=blue, arrowhead=dot]; + 238 -> "655E" [label=" ", color=blue, arrowhead=dot]; + 239 -> "657E" [label=" ", color=blue, arrowhead=dot]; + 240 -> "659E" [label=" ", color=blue, arrowhead=dot]; + 241 -> "661E" [label=" ", color=blue, arrowhead=dot]; + 242 -> "663E" [label=" ", color=blue, arrowhead=dot]; + 243 -> "665E" [label=" ", color=blue, arrowhead=dot]; + 244 -> "667E" [label=" ", color=blue, arrowhead=dot]; + 245 -> "669E" [label=" ", color=blue, arrowhead=dot]; + 246 -> "671E" [label=" ", color=blue, arrowhead=dot]; + 247 -> "673E" [label=" ", color=blue, arrowhead=dot]; + 248 -> "675E" [label=" ", color=blue, arrowhead=dot]; + 249 -> "679E" [label=" ", color=blue, arrowhead=dot]; + 251 -> "681E" [label=" ", color=blue, arrowhead=dot]; + 252 -> "683E" [label=" ", color=blue, arrowhead=dot]; + 253 -> "685E" [label=" ", color=blue, arrowhead=dot]; + 254 -> "687E" [label=" ", color=blue, arrowhead=dot]; + 255 -> "689E" [label=" ", color=blue, arrowhead=dot]; + 256 -> "691E" [label=" ", color=blue, arrowhead=dot]; + 257 -> "693E" [label=" ", color=blue, arrowhead=dot]; + 258 -> "695E" [label=" ", color=blue, arrowhead=dot]; + 259 -> "697E" [label=" ", color=blue, arrowhead=dot]; + 260 -> "699E" [label=" ", color=blue, arrowhead=dot]; + 261 -> "703E" [label=" ", color=blue, arrowhead=dot]; + 262 -> "705E" [label=" ", color=blue, arrowhead=dot]; + 264 -> "709E" [label=" ", color=blue, arrowhead=dot]; + 265 -> "711E" [label=" ", color=blue, arrowhead=dot]; + 266 -> "713E" [label=" ", color=blue, arrowhead=dot]; + 267 -> "715E" [label=" ", color=blue, arrowhead=dot]; + 268 -> "717E" [label=" ", color=blue, arrowhead=dot]; + 269 -> "719E" [label=" ", color=blue, arrowhead=dot]; + 270 -> "721E" [label=" ", color=blue, arrowhead=dot]; + 272 -> "34E" [label=" ", color=blue, arrowhead=dot]; + 272 -> "252E" [label=" ", color=blue, arrowhead=dot]; + 272 -> "436E" [label=" ", color=blue, arrowhead=dot]; + 274 -> "59E" [label=" ", color=blue, arrowhead=dot]; + 274 -> "500E" [label=" ", color=blue, arrowhead=dot]; + 274 -> "720E" [label=" ", color=blue, arrowhead=dot]; + 275 -> "98E" [label=" ", color=blue, arrowhead=dot]; + 278 -> "35E" [label=" ", color=blue, arrowhead=dot]; + 278 -> "488E" [label=" ", color=blue, arrowhead=dot]; + 278 -> "598E" [label=" ", color=blue, arrowhead=dot]; + 278 -> "604E" [label=" ", color=blue, arrowhead=dot]; + 278 -> "628E" [label=" ", color=blue, arrowhead=dot]; + 279 -> "99E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "242E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "270E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "272E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "284E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "286E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "288E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "586E" [label=" ", color=blue, arrowhead=dot]; + 280 -> "763E" [label=" ", color=blue, arrowhead=dot]; + 281 -> "45E" [label=" ", color=blue, arrowhead=dot]; + 281 -> "470E" [label=" ", color=blue, arrowhead=dot]; + 281 -> "670E" [label=" ", color=blue, arrowhead=dot]; + 281 -> "722E" [label=" ", color=blue, arrowhead=dot]; + 282 -> "103E" [label=" ", color=blue, arrowhead=dot]; + 283 -> "165E" [label=" ", color=blue, arrowhead=dot]; + 284 -> "39E" [label=" ", color=blue, arrowhead=dot]; + 284 -> "224E" [label=" ", color=blue, arrowhead=dot]; + 284 -> "268E" [label=" ", color=blue, arrowhead=dot]; + 284 -> "632E" [label=" ", color=blue, arrowhead=dot]; + 284 -> "710E" [label=" ", color=blue, arrowhead=dot]; + 285 -> "53E" [label=" ", color=blue, arrowhead=dot]; + 286 -> "38E" [label=" ", color=blue, arrowhead=dot]; + 286 -> "166E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "40E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "218E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "244E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "246E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "258E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "290E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "292E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "308E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "318E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "388E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "472E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "478E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "566E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "570E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "574E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "608E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "614E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "658E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "664E" [label=" ", color=blue, arrowhead=dot]; + 288 -> "682E" [label=" ", color=blue, arrowhead=dot]; + 289 -> "41E" [label=" ", color=blue, arrowhead=dot]; + 289 -> "636E" [label=" ", color=blue, arrowhead=dot]; + 289 -> "642E" [label=" ", color=blue, arrowhead=dot]; + 289 -> "690E" [label=" ", color=blue, arrowhead=dot]; + 289 -> "700E" [label=" ", color=blue, arrowhead=dot]; + 290 -> "56E" [label=" ", color=blue, arrowhead=dot]; + 290 -> "264E" [label=" ", color=blue, arrowhead=dot]; + 290 -> "510E" [label=" ", color=blue, arrowhead=dot]; + 290 -> "718E" [label=" ", color=blue, arrowhead=dot]; + 291 -> "66E" [label=" ", color=blue, arrowhead=dot]; + 291 -> "76E" [label=" ", color=blue, arrowhead=dot]; + 291 -> "610E" [label=" ", color=blue, arrowhead=dot]; + 292 -> "73E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "49E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "214E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "216E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "236E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "278E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "358E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "398E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "400E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "402E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "404E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "406E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "408E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "412E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "438E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "448E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "476E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "504E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "552E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "634E" [label=" ", color=blue, arrowhead=dot]; + 293 -> "768E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "44E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "92E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "250E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "316E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "380E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "424E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "442E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "446E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "454E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "460E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "462E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "648E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "656E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "666E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "692E" [label=" ", color=blue, arrowhead=dot]; + 295 -> "712E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "47E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "330E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "514E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "516E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "518E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "520E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "522E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "526E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "528E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "530E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "532E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "534E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "536E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "538E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "540E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "542E" [label=" ", color=blue, arrowhead=dot]; + 296 -> "544E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "46E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "93E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "206E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "426E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "550E" [label=" ", color=blue, arrowhead=dot]; + 297 -> "706E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "36E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "95E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "364E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "394E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "420E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "456E" [label=" ", color=blue, arrowhead=dot]; + 298 -> "624E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "48E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "168E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "260E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "282E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "554E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "590E" [label=" ", color=blue, arrowhead=dot]; + 299 -> "767E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "62E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "190E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "226E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "238E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "254E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "256E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "262E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "266E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "274E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "276E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "294E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "296E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "310E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "320E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "322E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "332E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "340E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "344E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "346E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "348E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "374E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "378E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "452E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "508E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "524E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "612E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "626E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "638E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "644E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "654E" [label=" ", color=blue, arrowhead=dot]; + 300 -> "672E" [label=" ", color=blue, arrowhead=dot]; + 302 -> "797E" [label=" ", color=blue, arrowhead=dot]; + 302 -> "798E" [label=" ", color=blue, arrowhead=dot]; + 303 -> "52E" [label=" ", color=blue, arrowhead=dot]; + 303 -> "650E" [label=" ", color=blue, arrowhead=dot]; + 304 -> "50E" [label=" ", color=blue, arrowhead=dot]; + 304 -> "640E" [label=" ", color=blue, arrowhead=dot]; + 304 -> "646E" [label=" ", color=blue, arrowhead=dot]; + 304 -> "652E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "55E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "220E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "338E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "368E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "486E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "490E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "562E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "564E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "600E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "668E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "674E" [label=" ", color=blue, arrowhead=dot]; + 306 -> "698E" [label=" ", color=blue, arrowhead=dot]; + 307 -> "107E" [label=" ", color=blue, arrowhead=dot]; + 308 -> "108E" [label=" ", color=blue, arrowhead=dot]; + 309 -> "109E" [label=" ", color=blue, arrowhead=dot]; + 310 -> "110E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "58E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "234E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "300E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "306E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "314E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "342E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "354E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "370E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "382E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "422E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "444E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "582E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "620E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "630E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "684E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "696E" [label=" ", color=blue, arrowhead=dot]; + 311 -> "801E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "42E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "192E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "194E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "196E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "198E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "200E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "202E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "204E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "312E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "336E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "376E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "384E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "386E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "428E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "474E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "484E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "546E" [label=" ", color=blue, arrowhead=dot]; + 312 -> "548E" [label=" ", color=blue, arrowhead=dot]; + 314 -> "113E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "43E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "240E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "298E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "334E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "360E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "390E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "418E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "492E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "502E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "584E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "588E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "602E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "606E" [label=" ", color=blue, arrowhead=dot]; + 315 -> "662E" [label=" ", color=blue, arrowhead=dot]; + 316 -> "51E" [label=" ", color=blue, arrowhead=dot]; + 317 -> "116E" [label=" ", color=blue, arrowhead=dot]; + 318 -> "74E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "57E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "94E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "350E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "440E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "466E" [label=" ", color=blue, arrowhead=dot]; + 319 -> "676E" [label=" ", color=blue, arrowhead=dot]; + 320 -> "60E" [label=" ", color=blue, arrowhead=dot]; + 320 -> "366E" [label=" ", color=blue, arrowhead=dot]; + 320 -> "434E" [label=" ", color=blue, arrowhead=dot]; + 320 -> "458E" [label=" ", color=blue, arrowhead=dot]; + 320 -> "618E" [label=" ", color=blue, arrowhead=dot]; + 321 -> "72E" [label=" ", color=blue, arrowhead=dot]; + 321 -> "362E" [label=" ", color=blue, arrowhead=dot]; + 321 -> "372E" [label=" ", color=blue, arrowhead=dot]; + 321 -> "572E" [label=" ", color=blue, arrowhead=dot]; + 322 -> "54E" [label=" ", color=blue, arrowhead=dot]; + 322 -> "222E" [label=" ", color=blue, arrowhead=dot]; + 322 -> "302E" [label=" ", color=blue, arrowhead=dot]; + 322 -> "556E" [label=" ", color=blue, arrowhead=dot]; + 322 -> "558E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "37E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "208E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "210E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "352E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "450E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "568E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "576E" [label=" ", color=blue, arrowhead=dot]; + 323 -> "686E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "228E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "248E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "304E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "468E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "578E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "660E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "688E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "694E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "714E" [label=" ", color=blue, arrowhead=dot]; + 324 -> "766E" [label=" ", color=blue, arrowhead=dot]; + 325 -> "97E" [label=" ", color=blue, arrowhead=dot]; + 325 -> "506E" [label=" ", color=blue, arrowhead=dot]; + 326 -> "61E" [label=" ", color=blue, arrowhead=dot]; + 326 -> "175E" [label=" ", color=blue, arrowhead=dot]; + 326 -> "482E" [label=" ", color=blue, arrowhead=dot]; + 328 -> "75E" [label=" ", color=blue, arrowhead=dot]; + 328 -> "580E" [label=" ", color=blue, arrowhead=dot]; + 329 -> "96E" [label=" ", color=blue, arrowhead=dot]; + 330 -> "100E" [label=" ", color=blue, arrowhead=dot]; + 330 -> "170E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "63E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "67E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "68E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "69E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "70E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "71E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "802E" [label=" ", color=blue, arrowhead=dot]; + 333 -> "793E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "64E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "81E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "82E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "83E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "84E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "85E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "86E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "87E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "88E" [label=" ", color=blue, arrowhead=dot]; + 334 -> "89E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "1E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "2E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "3E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "4E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "5E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "6E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "7E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "8E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "9E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "10E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "11E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "12E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "13E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "14E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "15E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "16E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "17E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "18E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "19E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "20E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "21E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "22E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "23E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "24E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "25E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "26E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "27E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "28E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "29E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "30E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "31E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "65E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "119E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "150E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "176E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "743E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "744E" [label=" ", color=blue, arrowhead=dot]; + 336 -> "764E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "120E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "121E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "122E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "123E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "124E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "125E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "126E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "127E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "128E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "129E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "130E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "131E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "132E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "133E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "134E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "135E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "136E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "137E" [label=" ", color=blue, arrowhead=dot]; + 337 -> "138E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "151E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "153E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "154E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "155E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "156E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "157E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "158E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "159E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "160E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "161E" [label=" ", color=blue, arrowhead=dot]; + 339 -> "162E" [label=" ", color=blue, arrowhead=dot]; + 347 -> "139E" [label=" ", color=blue, arrowhead=dot]; + 347 -> "795E" [label=" ", color=blue, arrowhead=dot]; + 348 -> "799E" [label=" ", color=blue, arrowhead=dot]; + 348 -> "800E" [label=" ", color=blue, arrowhead=dot]; + 349 -> "141E" [label=" ", color=blue, arrowhead=dot]; + 350 -> "142E" [label=" ", color=blue, arrowhead=dot]; + 350 -> "678E" [label=" ", color=blue, arrowhead=dot]; + 351 -> "143E" [label=" ", color=blue, arrowhead=dot]; + 351 -> "232E" [label=" ", color=blue, arrowhead=dot]; + 351 -> "680E" [label=" ", color=blue, arrowhead=dot]; + 351 -> "704E" [label=" ", color=blue, arrowhead=dot]; + 352 -> "144E" [label=" ", color=blue, arrowhead=dot]; + 352 -> "432E" [label=" ", color=blue, arrowhead=dot]; + 353 -> "145E" [label=" ", color=blue, arrowhead=dot]; + 354 -> "146E" [label=" ", color=blue, arrowhead=dot]; + 354 -> "396E" [label=" ", color=blue, arrowhead=dot]; + 355 -> "147E" [label=" ", color=blue, arrowhead=dot]; + 356 -> "148E" [label=" ", color=blue, arrowhead=dot]; + 357 -> "149E" [label=" ", color=blue, arrowhead=dot]; + 358 -> "167E" [label=" ", color=blue, arrowhead=dot]; + 359 -> "169E" [label=" ", color=blue, arrowhead=dot]; + 360 -> "171E" [label=" ", color=blue, arrowhead=dot]; + 361 -> "172E" [label=" ", color=blue, arrowhead=dot]; + 362 -> "173E" [label=" ", color=blue, arrowhead=dot]; + 363 -> "174E" [label=" ", color=blue, arrowhead=dot]; + 364 -> "101E" [label=" ", color=blue, arrowhead=dot]; + 365 -> "102E" [label=" ", color=blue, arrowhead=dot]; + 367 -> "104E" [label=" ", color=blue, arrowhead=dot]; + 368 -> "105E" [label=" ", color=blue, arrowhead=dot]; + 369 -> "106E" [label=" ", color=blue, arrowhead=dot]; + 374 -> "111E" [label=" ", color=blue, arrowhead=dot]; + 375 -> "112E" [label=" ", color=blue, arrowhead=dot]; + 377 -> "114E" [label=" ", color=blue, arrowhead=dot]; + 378 -> "115E" [label=" ", color=blue, arrowhead=dot]; + 380 -> "117E" [label=" ", color=blue, arrowhead=dot]; + 380 -> "392E" [label=" ", color=blue, arrowhead=dot]; + 381 -> "118E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "177E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "178E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "179E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "180E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "181E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "182E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "183E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "184E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "185E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "186E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "187E" [label=" ", color=blue, arrowhead=dot]; + 382 -> "188E" [label=" ", color=blue, arrowhead=dot]; + 383 -> "730E" [label=" ", color=blue, arrowhead=dot]; + 383 -> "732E" [label=" ", color=blue, arrowhead=dot]; + 383 -> "741E" [label=" ", color=blue, arrowhead=dot]; + 383 -> "765E" [label=" ", color=blue, arrowhead=dot]; + 383 -> "796E" [label=" ", color=blue, arrowhead=dot]; + 384 -> "726E" [label=" ", color=blue, arrowhead=dot]; + 384 -> "728E" [label=" ", color=blue, arrowhead=dot]; + 384 -> "742E" [label=" ", color=blue, arrowhead=dot]; + "1E" -> "34E" [color=purple, arrowhead=none]; + "2E" -> "35E" [color=purple, arrowhead=none]; + "3E" -> "36E" [color=purple, arrowhead=none]; + "4E" -> "37E" [color=purple, arrowhead=none]; + "5E" -> "38E" [color=purple, arrowhead=none]; + "6E" -> "39E" [color=purple, arrowhead=none]; + "7E" -> "40E" [color=purple, arrowhead=none]; + "9E" -> "41E" [color=purple, arrowhead=none]; + "10E" -> "42E" [color=purple, arrowhead=none]; + "11E" -> "43E" [color=purple, arrowhead=none]; + "12E" -> "44E" [color=purple, arrowhead=none]; + "13E" -> "45E" [color=purple, arrowhead=none]; + "14E" -> "46E" [color=purple, arrowhead=none]; + "15E" -> "47E" [color=purple, arrowhead=none]; + "16E" -> "48E" [color=purple, arrowhead=none]; + "49E" -> "17E" [color=purple, arrowhead=none]; + "18E" -> "50E" [color=purple, arrowhead=none]; + "19E" -> "51E" [color=purple, arrowhead=none]; + "20E" -> "52E" [color=purple, arrowhead=none]; + "21E" -> "53E" [color=purple, arrowhead=none]; + "22E" -> "54E" [color=purple, arrowhead=none]; + "23E" -> "55E" [color=purple, arrowhead=none]; + "24E" -> "56E" [color=purple, arrowhead=none]; + "25E" -> "57E" [color=purple, arrowhead=none]; + "26E" -> "58E" [color=purple, arrowhead=none]; + "27E" -> "59E" [color=purple, arrowhead=none]; + "28E" -> "60E" [color=purple, arrowhead=none]; + "29E" -> "61E" [color=purple, arrowhead=none]; + "30E" -> "62E" [color=purple, arrowhead=none]; + "31E" -> "63E" [color=purple, arrowhead=none]; + "64E" -> "65E" [color=purple, arrowhead=none]; + "66E" -> "8E" [color=purple, arrowhead=none]; + "71E" -> "76E" [color=purple, arrowhead=none]; + "67E" -> "72E" [color=purple, arrowhead=none]; + "68E" -> "73E" [color=purple, arrowhead=none]; + "69E" -> "74E" [color=purple, arrowhead=none]; + "70E" -> "75E" [color=purple, arrowhead=none]; + "81E" -> "92E" [color=purple, arrowhead=none]; + "82E" -> "93E" [color=purple, arrowhead=none]; + "83E" -> "94E" [color=purple, arrowhead=none]; + "84E" -> "95E" [color=purple, arrowhead=none]; + "85E" -> "96E" [color=purple, arrowhead=none]; + "86E" -> "97E" [color=purple, arrowhead=none]; + "87E" -> "98E" [color=purple, arrowhead=none]; + "88E" -> "99E" [color=purple, arrowhead=none]; + "89E" -> "100E" [color=purple, arrowhead=none]; + "101E" -> "120E" [color=purple, arrowhead=none]; + "102E" -> "121E" [color=purple, arrowhead=none]; + "103E" -> "122E" [color=purple, arrowhead=none]; + "104E" -> "123E" [color=purple, arrowhead=none]; + "105E" -> "124E" [color=purple, arrowhead=none]; + "106E" -> "125E" [color=purple, arrowhead=none]; + "107E" -> "126E" [color=purple, arrowhead=none]; + "108E" -> "127E" [color=purple, arrowhead=none]; + "109E" -> "128E" [color=purple, arrowhead=none]; + "110E" -> "129E" [color=purple, arrowhead=none]; + "111E" -> "130E" [color=purple, arrowhead=none]; + "112E" -> "131E" [color=purple, arrowhead=none]; + "113E" -> "132E" [color=purple, arrowhead=none]; + "114E" -> "133E" [color=purple, arrowhead=none]; + "115E" -> "134E" [color=purple, arrowhead=none]; + "116E" -> "135E" [color=purple, arrowhead=none]; + "117E" -> "136E" [color=purple, arrowhead=none]; + "118E" -> "137E" [color=purple, arrowhead=none]; + "119E" -> "138E" [color=purple, arrowhead=none]; + "139E" -> "151E" [color=purple, arrowhead=none]; + "141E" -> "153E" [color=purple, arrowhead=none]; + "142E" -> "154E" [color=purple, arrowhead=none]; + "143E" -> "155E" [color=purple, arrowhead=none]; + "144E" -> "156E" [color=purple, arrowhead=none]; + "145E" -> "157E" [color=purple, arrowhead=none]; + "146E" -> "158E" [color=purple, arrowhead=none]; + "147E" -> "159E" [color=purple, arrowhead=none]; + "148E" -> "160E" [color=purple, arrowhead=none]; + "149E" -> "161E" [color=purple, arrowhead=none]; + "150E" -> "162E" [color=purple, arrowhead=none]; + "165E" -> "177E" [color=purple, arrowhead=none]; + "166E" -> "178E" [color=purple, arrowhead=none]; + "167E" -> "179E" [color=purple, arrowhead=none]; + "168E" -> "180E" [color=purple, arrowhead=none]; + "169E" -> "181E" [color=purple, arrowhead=none]; + "170E" -> "182E" [color=purple, arrowhead=none]; + "171E" -> "183E" [color=purple, arrowhead=none]; + "172E" -> "184E" [color=purple, arrowhead=none]; + "173E" -> "185E" [color=purple, arrowhead=none]; + "174E" -> "186E" [color=purple, arrowhead=none]; + "175E" -> "187E" [color=purple, arrowhead=none]; + "176E" -> "188E" [color=purple, arrowhead=none]; + "189E" -> "190E" [color=purple, arrowhead=none]; + "191E" -> "192E" [color=purple, arrowhead=none]; + "193E" -> "194E" [color=purple, arrowhead=none]; + "195E" -> "196E" [color=purple, arrowhead=none]; + "197E" -> "198E" [color=purple, arrowhead=none]; + "199E" -> "200E" [color=purple, arrowhead=none]; + "201E" -> "202E" [color=purple, arrowhead=none]; + "203E" -> "204E" [color=purple, arrowhead=none]; + "205E" -> "206E" [color=purple, arrowhead=none]; + "207E" -> "208E" [color=purple, arrowhead=none]; + "209E" -> "210E" [color=purple, arrowhead=none]; + "412E" -> "211E" [color=purple, arrowhead=none]; + "214E" -> "213E" [color=purple, arrowhead=none]; + "216E" -> "215E" [color=purple, arrowhead=none]; + "217E" -> "218E" [color=purple, arrowhead=none]; + "219E" -> "220E" [color=purple, arrowhead=none]; + "221E" -> "222E" [color=purple, arrowhead=none]; + "223E" -> "224E" [color=purple, arrowhead=none]; + "225E" -> "226E" [color=purple, arrowhead=none]; + "227E" -> "228E" [color=purple, arrowhead=none]; + "231E" -> "232E" [color=purple, arrowhead=none]; + "233E" -> "234E" [color=purple, arrowhead=none]; + "236E" -> "235E" [color=purple, arrowhead=none]; + "237E" -> "238E" [color=purple, arrowhead=none]; + "239E" -> "240E" [color=purple, arrowhead=none]; + "241E" -> "242E" [color=purple, arrowhead=none]; + "243E" -> "244E" [color=purple, arrowhead=none]; + "245E" -> "246E" [color=purple, arrowhead=none]; + "247E" -> "248E" [color=purple, arrowhead=none]; + "249E" -> "250E" [color=purple, arrowhead=none]; + "251E" -> "252E" [color=purple, arrowhead=none]; + "253E" -> "254E" [color=purple, arrowhead=none]; + "255E" -> "256E" [color=purple, arrowhead=none]; + "257E" -> "258E" [color=purple, arrowhead=none]; + "259E" -> "260E" [color=purple, arrowhead=none]; + "261E" -> "262E" [color=purple, arrowhead=none]; + "263E" -> "264E" [color=purple, arrowhead=none]; + "265E" -> "266E" [color=purple, arrowhead=none]; + "267E" -> "268E" [color=purple, arrowhead=none]; + "269E" -> "270E" [color=purple, arrowhead=none]; + "271E" -> "272E" [color=purple, arrowhead=none]; + "273E" -> "274E" [color=purple, arrowhead=none]; + "275E" -> "276E" [color=purple, arrowhead=none]; + "278E" -> "277E" [color=purple, arrowhead=none]; + "279E" -> "767E" [color=purple, arrowhead=none]; + "281E" -> "282E" [color=purple, arrowhead=none]; + "283E" -> "284E" [color=purple, arrowhead=none]; + "285E" -> "286E" [color=purple, arrowhead=none]; + "768E" -> "287E" [color=purple, arrowhead=none]; + "289E" -> "290E" [color=purple, arrowhead=none]; + "291E" -> "292E" [color=purple, arrowhead=none]; + "293E" -> "294E" [color=purple, arrowhead=none]; + "295E" -> "296E" [color=purple, arrowhead=none]; + "297E" -> "298E" [color=purple, arrowhead=none]; + "299E" -> "300E" [color=purple, arrowhead=none]; + "301E" -> "302E" [color=purple, arrowhead=none]; + "303E" -> "304E" [color=purple, arrowhead=none]; + "305E" -> "306E" [color=purple, arrowhead=none]; + "307E" -> "308E" [color=purple, arrowhead=none]; + "309E" -> "310E" [color=purple, arrowhead=none]; + "311E" -> "312E" [color=purple, arrowhead=none]; + "313E" -> "314E" [color=purple, arrowhead=none]; + "315E" -> "316E" [color=purple, arrowhead=none]; + "317E" -> "318E" [color=purple, arrowhead=none]; + "319E" -> "320E" [color=purple, arrowhead=none]; + "321E" -> "322E" [color=purple, arrowhead=none]; + "327E" -> "800E" [color=purple, arrowhead=none]; + "329E" -> "330E" [color=purple, arrowhead=none]; + "331E" -> "332E" [color=purple, arrowhead=none]; + "333E" -> "334E" [color=purple, arrowhead=none]; + "335E" -> "336E" [color=purple, arrowhead=none]; + "337E" -> "338E" [color=purple, arrowhead=none]; + "339E" -> "340E" [color=purple, arrowhead=none]; + "341E" -> "342E" [color=purple, arrowhead=none]; + "343E" -> "344E" [color=purple, arrowhead=none]; + "345E" -> "346E" [color=purple, arrowhead=none]; + "347E" -> "348E" [color=purple, arrowhead=none]; + "349E" -> "350E" [color=purple, arrowhead=none]; + "351E" -> "352E" [color=purple, arrowhead=none]; + "353E" -> "354E" [color=purple, arrowhead=none]; + "412E" -> "355E" [color=purple, arrowhead=none]; + "357E" -> "358E" [color=purple, arrowhead=none]; + "359E" -> "360E" [color=purple, arrowhead=none]; + "361E" -> "362E" [color=purple, arrowhead=none]; + "363E" -> "364E" [color=purple, arrowhead=none]; + "365E" -> "366E" [color=purple, arrowhead=none]; + "367E" -> "368E" [color=purple, arrowhead=none]; + "369E" -> "370E" [color=purple, arrowhead=none]; + "371E" -> "372E" [color=purple, arrowhead=none]; + "373E" -> "374E" [color=purple, arrowhead=none]; + "375E" -> "376E" [color=purple, arrowhead=none]; + "377E" -> "378E" [color=purple, arrowhead=none]; + "379E" -> "380E" [color=purple, arrowhead=none]; + "381E" -> "382E" [color=purple, arrowhead=none]; + "383E" -> "384E" [color=purple, arrowhead=none]; + "385E" -> "386E" [color=purple, arrowhead=none]; + "387E" -> "388E" [color=purple, arrowhead=none]; + "389E" -> "390E" [color=purple, arrowhead=none]; + "391E" -> "392E" [color=purple, arrowhead=none]; + "393E" -> "394E" [color=purple, arrowhead=none]; + "395E" -> "396E" [color=purple, arrowhead=none]; + "397E" -> "398E" [color=purple, arrowhead=none]; + "399E" -> "400E" [color=purple, arrowhead=none]; + "402E" -> "401E" [color=purple, arrowhead=none]; + "404E" -> "403E" [color=purple, arrowhead=none]; + "406E" -> "405E" [color=purple, arrowhead=none]; + "408E" -> "407E" [color=purple, arrowhead=none]; + "236E" -> "409E" [color=purple, arrowhead=none]; + "412E" -> "411E" [color=purple, arrowhead=none]; + "412E" -> "413E" [color=purple, arrowhead=none]; + "278E" -> "415E" [color=purple, arrowhead=none]; + "417E" -> "418E" [color=purple, arrowhead=none]; + "419E" -> "420E" [color=purple, arrowhead=none]; + "421E" -> "422E" [color=purple, arrowhead=none]; + "423E" -> "424E" [color=purple, arrowhead=none]; + "425E" -> "426E" [color=purple, arrowhead=none]; + "427E" -> "428E" [color=purple, arrowhead=none]; + "431E" -> "432E" [color=purple, arrowhead=none]; + "433E" -> "434E" [color=purple, arrowhead=none]; + "435E" -> "436E" [color=purple, arrowhead=none]; + "438E" -> "437E" [color=purple, arrowhead=none]; + "439E" -> "440E" [color=purple, arrowhead=none]; + "441E" -> "442E" [color=purple, arrowhead=none]; + "443E" -> "444E" [color=purple, arrowhead=none]; + "445E" -> "446E" [color=purple, arrowhead=none]; + "448E" -> "447E" [color=purple, arrowhead=none]; + "449E" -> "450E" [color=purple, arrowhead=none]; + "451E" -> "452E" [color=purple, arrowhead=none]; + "453E" -> "454E" [color=purple, arrowhead=none]; + "455E" -> "456E" [color=purple, arrowhead=none]; + "457E" -> "458E" [color=purple, arrowhead=none]; + "459E" -> "460E" [color=purple, arrowhead=none]; + "461E" -> "462E" [color=purple, arrowhead=none]; + "236E" -> "463E" [color=purple, arrowhead=none]; + "465E" -> "466E" [color=purple, arrowhead=none]; + "467E" -> "468E" [color=purple, arrowhead=none]; + "469E" -> "470E" [color=purple, arrowhead=none]; + "471E" -> "472E" [color=purple, arrowhead=none]; + "473E" -> "474E" [color=purple, arrowhead=none]; + "476E" -> "475E" [color=purple, arrowhead=none]; + "477E" -> "478E" [color=purple, arrowhead=none]; + "479E" -> "358E" [color=purple, arrowhead=none]; + "481E" -> "482E" [color=purple, arrowhead=none]; + "483E" -> "484E" [color=purple, arrowhead=none]; + "485E" -> "486E" [color=purple, arrowhead=none]; + "487E" -> "488E" [color=purple, arrowhead=none]; + "489E" -> "490E" [color=purple, arrowhead=none]; + "491E" -> "492E" [color=purple, arrowhead=none]; + "495E" -> "795E" [color=purple, arrowhead=none]; + "499E" -> "500E" [color=purple, arrowhead=none]; + "501E" -> "502E" [color=purple, arrowhead=none]; + "504E" -> "503E" [color=purple, arrowhead=none]; + "505E" -> "506E" [color=purple, arrowhead=none]; + "507E" -> "508E" [color=purple, arrowhead=none]; + "509E" -> "510E" [color=purple, arrowhead=none]; + "412E" -> "511E" [color=purple, arrowhead=none]; + "513E" -> "514E" [color=purple, arrowhead=none]; + "515E" -> "516E" [color=purple, arrowhead=none]; + "517E" -> "518E" [color=purple, arrowhead=none]; + "519E" -> "520E" [color=purple, arrowhead=none]; + "521E" -> "522E" [color=purple, arrowhead=none]; + "523E" -> "524E" [color=purple, arrowhead=none]; + "525E" -> "526E" [color=purple, arrowhead=none]; + "527E" -> "528E" [color=purple, arrowhead=none]; + "529E" -> "530E" [color=purple, arrowhead=none]; + "531E" -> "532E" [color=purple, arrowhead=none]; + "533E" -> "534E" [color=purple, arrowhead=none]; + "535E" -> "536E" [color=purple, arrowhead=none]; + "537E" -> "538E" [color=purple, arrowhead=none]; + "539E" -> "540E" [color=purple, arrowhead=none]; + "541E" -> "542E" [color=purple, arrowhead=none]; + "543E" -> "544E" [color=purple, arrowhead=none]; + "545E" -> "546E" [color=purple, arrowhead=none]; + "547E" -> "548E" [color=purple, arrowhead=none]; + "549E" -> "550E" [color=purple, arrowhead=none]; + "551E" -> "552E" [color=purple, arrowhead=none]; + "553E" -> "554E" [color=purple, arrowhead=none]; + "555E" -> "556E" [color=purple, arrowhead=none]; + "557E" -> "558E" [color=purple, arrowhead=none]; + "278E" -> "559E" [color=purple, arrowhead=none]; + "561E" -> "562E" [color=purple, arrowhead=none]; + "563E" -> "564E" [color=purple, arrowhead=none]; + "565E" -> "566E" [color=purple, arrowhead=none]; + "567E" -> "568E" [color=purple, arrowhead=none]; + "569E" -> "570E" [color=purple, arrowhead=none]; + "571E" -> "572E" [color=purple, arrowhead=none]; + "573E" -> "574E" [color=purple, arrowhead=none]; + "575E" -> "576E" [color=purple, arrowhead=none]; + "577E" -> "578E" [color=purple, arrowhead=none]; + "579E" -> "580E" [color=purple, arrowhead=none]; + "581E" -> "582E" [color=purple, arrowhead=none]; + "583E" -> "584E" [color=purple, arrowhead=none]; + "585E" -> "586E" [color=purple, arrowhead=none]; + "587E" -> "588E" [color=purple, arrowhead=none]; + "589E" -> "590E" [color=purple, arrowhead=none]; + "597E" -> "598E" [color=purple, arrowhead=none]; + "599E" -> "600E" [color=purple, arrowhead=none]; + "601E" -> "602E" [color=purple, arrowhead=none]; + "603E" -> "604E" [color=purple, arrowhead=none]; + "605E" -> "606E" [color=purple, arrowhead=none]; + "607E" -> "608E" [color=purple, arrowhead=none]; + "609E" -> "610E" [color=purple, arrowhead=none]; + "611E" -> "612E" [color=purple, arrowhead=none]; + "613E" -> "614E" [color=purple, arrowhead=none]; + "615E" -> "358E" [color=purple, arrowhead=none]; + "617E" -> "618E" [color=purple, arrowhead=none]; + "619E" -> "620E" [color=purple, arrowhead=none]; + "623E" -> "624E" [color=purple, arrowhead=none]; + "625E" -> "626E" [color=purple, arrowhead=none]; + "627E" -> "628E" [color=purple, arrowhead=none]; + "629E" -> "630E" [color=purple, arrowhead=none]; + "631E" -> "632E" [color=purple, arrowhead=none]; + "634E" -> "633E" [color=purple, arrowhead=none]; + "635E" -> "636E" [color=purple, arrowhead=none]; + "637E" -> "638E" [color=purple, arrowhead=none]; + "639E" -> "640E" [color=purple, arrowhead=none]; + "641E" -> "642E" [color=purple, arrowhead=none]; + "643E" -> "644E" [color=purple, arrowhead=none]; + "645E" -> "646E" [color=purple, arrowhead=none]; + "647E" -> "648E" [color=purple, arrowhead=none]; + "649E" -> "650E" [color=purple, arrowhead=none]; + "651E" -> "652E" [color=purple, arrowhead=none]; + "653E" -> "654E" [color=purple, arrowhead=none]; + "655E" -> "656E" [color=purple, arrowhead=none]; + "657E" -> "658E" [color=purple, arrowhead=none]; + "659E" -> "660E" [color=purple, arrowhead=none]; + "661E" -> "662E" [color=purple, arrowhead=none]; + "663E" -> "664E" [color=purple, arrowhead=none]; + "665E" -> "666E" [color=purple, arrowhead=none]; + "667E" -> "668E" [color=purple, arrowhead=none]; + "669E" -> "670E" [color=purple, arrowhead=none]; + "671E" -> "672E" [color=purple, arrowhead=none]; + "673E" -> "674E" [color=purple, arrowhead=none]; + "675E" -> "676E" [color=purple, arrowhead=none]; + "679E" -> "680E" [color=purple, arrowhead=none]; + "681E" -> "682E" [color=purple, arrowhead=none]; + "683E" -> "684E" [color=purple, arrowhead=none]; + "685E" -> "686E" [color=purple, arrowhead=none]; + "687E" -> "688E" [color=purple, arrowhead=none]; + "689E" -> "690E" [color=purple, arrowhead=none]; + "691E" -> "692E" [color=purple, arrowhead=none]; + "693E" -> "694E" [color=purple, arrowhead=none]; + "695E" -> "696E" [color=purple, arrowhead=none]; + "697E" -> "698E" [color=purple, arrowhead=none]; + "699E" -> "700E" [color=purple, arrowhead=none]; + "703E" -> "704E" [color=purple, arrowhead=none]; + "705E" -> "706E" [color=purple, arrowhead=none]; + "709E" -> "710E" [color=purple, arrowhead=none]; + "711E" -> "712E" [color=purple, arrowhead=none]; + "713E" -> "714E" [color=purple, arrowhead=none]; + "715E" -> "398E" [color=purple, arrowhead=none]; + "717E" -> "718E" [color=purple, arrowhead=none]; + "719E" -> "720E" [color=purple, arrowhead=none]; + "721E" -> "722E" [color=purple, arrowhead=none]; + "725E" -> "726E" [color=purple, arrowhead=none]; + "727E" -> "728E" [color=purple, arrowhead=none]; + "729E" -> "730E" [color=purple, arrowhead=none]; + "731E" -> "732E" [color=purple, arrowhead=none]; + "741E" -> "743E" [color=purple, arrowhead=none]; + "742E" -> "744E" [color=purple, arrowhead=none]; + "763E" -> "764E" [color=purple, arrowhead=none]; + "765E" -> "766E" [color=purple, arrowhead=none]; + "770E" -> "783E" [color=purple, arrowhead=none]; + "770E" -> "784E" [color=purple, arrowhead=none]; + "769E" -> "785E" [color=purple, arrowhead=none]; + "769E" -> "786E" [color=purple, arrowhead=none]; + "769E" -> "787E" [color=purple, arrowhead=none]; + "770E" -> "788E" [color=purple, arrowhead=none]; + "770E" -> "789E" [color=purple, arrowhead=none]; + "769E" -> "790E" [color=purple, arrowhead=none]; + "770E" -> "791E" [color=purple, arrowhead=none]; + "769E" -> "792E" [color=purple, arrowhead=none]; + "793E" -> "769E" [color=purple, arrowhead=none]; + "769E" -> "784E" [color=purple, arrowhead=none]; + "770E" -> "785E" [color=purple, arrowhead=none]; + "788E" -> "787E" [color=purple, arrowhead=none]; + "770E" -> "792E" [color=purple, arrowhead=none]; + "798E" -> "799E" [color=purple, arrowhead=none]; + "796E" -> "797E" [color=purple, arrowhead=none]; + "793E" -> "789E" [color=purple, arrowhead=none]; + "783E" -> "787E" [color=purple, arrowhead=none]; + "784E" -> "792E" [color=purple, arrowhead=none]; + "787E" -> "789E" [color=purple, arrowhead=none]; + "769E" -> "791E" [color=purple, arrowhead=none]; + "802E" -> "801E" [color=purple, arrowhead=none]; +} diff --git a/dot/2.dot b/dot/2.dot new file mode 100644 index 0000000..fa95abc --- /dev/null +++ b/dot/2.dot @@ -0,0 +1,27 @@ +digraph G { + + subgraph cluster_0 { + style=filled; + color=lightgrey; + node [style=filled,color=white]; + a0 -> a1 -> a2 -> a3; + label = "process #1"; + } + + subgraph cluster_1 { + node [style=filled]; + b0 -> b1 -> b2 -> b3; + label = "process #2"; + color=blue + } + start -> a0; + start -> b0; + a1 -> b3; + b2 -> a3; + a3 -> a0; + a3 -> end; + b3 -> end; + + start [shape=Mdiamond]; + end [shape=Msquare]; +} diff --git a/dot/3.dot b/dot/3.dot new file mode 100644 index 0000000..b51d498 --- /dev/null +++ b/dot/3.dot @@ -0,0 +1,104 @@ +digraph "unix" { + graph [ fontname = "Helvetica-Oblique", + fontsize = 36, + label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93", + size = "6,6" ]; + node [ shape = polygon, + sides = 4, + distortion = "0.0", + orientation = "0.0", + skew = "0.0", + color = white, + style = filled, + fontname = "Helvetica-Outline" ]; + "5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2]; + "6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue]; + "PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2]; + LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2]; + "1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1]; + "Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow]; + Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen]; + Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1]; + "Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2]; + "PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3]; + "7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate]; + "8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3]; + "32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3]; + V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy]; + "Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4]; + Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral]; + "UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3]; + "9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3]; + "2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond]; + "2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1]; + "2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2]; + "3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon]; + "4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1]; + "4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1]; + "4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4]; + "4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2]; + "Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3]; + "PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan]; + "USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue]; + "CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick]; + "USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4]; + "CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow]; + "CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4]; + "Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2]; + "PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1]; + "USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2]; + "Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered]; + "TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson]; + "System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1]; + "System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4]; + "System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1]; + "5th Edition" -> "6th Edition"; + "5th Edition" -> "PWB 1.0"; + "6th Edition" -> LSX; + "6th Edition" -> "1 BSD"; + "6th Edition" -> "Mini Unix"; + "6th Edition" -> Wollongong; + "6th Edition" -> Interdata; + Interdata -> "Unix/TS 3.0"; + Interdata -> "PWB 2.0"; + Interdata -> "7th Edition"; + "7th Edition" -> "8th Edition"; + "7th Edition" -> "32V"; + "7th Edition" -> V7M; + "7th Edition" -> "Ultrix-11"; + "7th Edition" -> Xenix; + "7th Edition" -> "UniPlus+"; + V7M -> "Ultrix-11"; + "8th Edition" -> "9th Edition"; + "1 BSD" -> "2 BSD"; + "2 BSD" -> "2.8 BSD"; + "2.8 BSD" -> "Ultrix-11"; + "2.8 BSD" -> "2.9 BSD"; + "32V" -> "3 BSD"; + "3 BSD" -> "4 BSD"; + "4 BSD" -> "4.1 BSD"; + "4.1 BSD" -> "4.2 BSD"; + "4.1 BSD" -> "2.8 BSD"; + "4.1 BSD" -> "8th Edition"; + "4.2 BSD" -> "4.3 BSD"; + "4.2 BSD" -> "Ultrix-32"; + "PWB 1.0" -> "PWB 1.2"; + "PWB 1.0" -> "USG 1.0"; + "PWB 1.2" -> "PWB 2.0"; + "USG 1.0" -> "CB Unix 1"; + "USG 1.0" -> "USG 2.0"; + "CB Unix 1" -> "CB Unix 2"; + "CB Unix 2" -> "CB Unix 3"; + "CB Unix 3" -> "Unix/TS++"; + "CB Unix 3" -> "PDP-11 Sys V"; + "USG 2.0" -> "USG 3.0"; + "USG 3.0" -> "Unix/TS 3.0"; + "PWB 2.0" -> "Unix/TS 3.0"; + "Unix/TS 1.0" -> "Unix/TS 3.0"; + "Unix/TS 3.0" -> "TS 4.0"; + "Unix/TS++" -> "TS 4.0"; + "CB Unix 3" -> "TS 4.0"; + "TS 4.0" -> "System V.0"; + "System V.0" -> "System V.2"; + "System V.2" -> "System V.3"; +} diff --git a/dot/4.dot b/dot/4.dot new file mode 100644 index 0000000..e59b7c2 --- /dev/null +++ b/dot/4.dot @@ -0,0 +1,20 @@ +digraph finite_state_machine { + rankdir=LR; + size="8,5" + node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; + node [shape = circle]; + LR_0 -> LR_2 [ label = "SS(B)" ]; + LR_0 -> LR_1 [ label = "SS(S)" ]; + LR_1 -> LR_3 [ label = "S($end)" ]; + LR_2 -> LR_6 [ label = "SS(b)" ]; + LR_2 -> LR_5 [ label = "SS(a)" ]; + LR_2 -> LR_4 [ label = "S(A)" ]; + LR_5 -> LR_7 [ label = "S(b)" ]; + LR_5 -> LR_5 [ label = "S(a)" ]; + LR_6 -> LR_6 [ label = "S(b)" ]; + LR_6 -> LR_5 [ label = "S(a)" ]; + LR_7 -> LR_8 [ label = "S(b)" ]; + LR_7 -> LR_5 [ label = "S(a)" ]; + LR_8 -> LR_6 [ label = "S(b)" ]; + LR_8 -> LR_5 [ label = "S(a)" ]; +} diff --git a/dot/5.dot b/dot/5.dot new file mode 100644 index 0000000..72b28fa --- /dev/null +++ b/dot/5.dot @@ -0,0 +1,2212 @@ +digraph G { + ranksep=3; + ratio=auto; +"1" [ label="02f5daf56e299b8a8ecea892",shape="hexagon",style="filled",color="green" ]; +"189E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; +"790E" [ label="b4dfef6",shape="box",style="filled",color="grey" ]; +"2" [ label="171192dc1f8e6ea551548a910c00",shape="hexagon",style="filled",color="green" ]; +"191E" [ label="629e42",shape="box",style="filled",color="grey" ]; +"3" [ label="6bce02baf91781a831e1b95",shape="hexagon",style="filled",color="green" ]; +"193E" [ label="1c08373",shape="box",style="filled",color="grey" ]; +"4" [ label="6236a67933a619a6a3d48",shape="hexagon",style="filled",color="green" ]; +"195E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; +"5" [ label="50962c93b4cb293f5beb59eb",shape="hexagon",style="filled",color="green" ]; +"197E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; +"6" [ label="05d4b1ed6a6135eec3abd3f2",shape="hexagon",style="filled",color="green" ]; +"199E" [ label="",shape="box",style="filled",color="grey" ]; +"7" [ label="08769f73d31c1a99be2d9363f",shape="hexagon",style="filled",color="green" ]; +"201E" [ label="629e42",shape="box",style="filled",color="grey" ]; +"8" [ label="a6a196a504c3a7657d1fa41",shape="hexagon",style="filled",color="green" ]; +"203E" [ label="cd856f",shape="box",style="filled",color="grey" ]; +"9" [ label="837ebf4bde22e1f1535cb662",shape="hexagon",style="filled",color="green" ]; +"725E" [ label="d0eb84",shape="box",style="filled",color="grey" ]; +"785E" [ label="dd2ba36",shape="box",style="filled",color="grey" ]; +"10" [ label="5f865c374cb3fe976dd376b8",shape="hexagon",style="filled",color="green" ]; +"205E" [ label="23ad1",shape="box",style="filled",color="grey" ]; +"11" [ label="8be752bc95d436a90493bec9",shape="hexagon",style="filled",color="green" ]; +"207E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; +"12" [ label="969a58db14386cb9d2f51ec",shape="hexagon",style="filled",color="green" ]; +"209E" [ label="7c7c",shape="box",style="filled",color="grey" ]; +"13" [ label="da24f74aad2ff519009d1f38c",shape="hexagon",style="filled",color="green" ]; +"211E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; +"14" [ label="3124d3a6ed3381a6341c6",shape="hexagon",style="filled",color="green" ]; +"213E" [ label="bbe0a8f93dc1",shape="box",style="filled",color="grey" ]; +"15" [ label="71512ec7d43f958f2b6da",shape="hexagon",style="filled",color="green" ]; +"215E" [ label="3f0a2b4eb62f",shape="box",style="filled",color="grey" ]; +"16" [ label="3828a2c682419423cf",shape="hexagon",style="filled",color="green" ]; +"727E" [ label="2",shape="box",style="filled",color="grey" ]; +"784E" [ label="",shape="box",style="filled",color="grey" ]; +"17" [ label="aa868f65c34cdb64f1fad19a",shape="hexagon",style="filled",color="green" ]; +"217E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; +"787E" [ label="1aaaab063",shape="box",style="filled",color="grey" ]; +"18" [ label="dca32af03698c988b22",shape="hexagon",style="filled",color="green" ]; +"219E" [ label="eb8",shape="box",style="filled",color="grey" ]; +"19" [ label="d8f4a9e463a1e89217f",shape="hexagon",style="filled",color="green" ]; +"221E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; +"20" [ label="c96782ef56711c5d6a3f69",shape="hexagon",style="filled",color="green" ]; +"223E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; +"21" [ label="4f04c39708f",shape="hexagon",style="filled",color="green" ]; +"225E" [ label="a49284e9",shape="box",style="filled",color="grey" ]; +"22" [ label="97284d4c3a5d499853f0e",shape="hexagon",style="filled",color="green" ]; +"227E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; +"792E" [ label="79b69c612",shape="box",style="filled",color="grey" ]; +"23" [ label="c4d32527b670afb370d643",shape="hexagon",style="filled",color="green" ]; +"231E" [ label="e851f5ddd920",shape="box",style="filled",color="grey" ]; +"24" [ label="5e9156098c064",shape="hexagon",style="filled",color="green" ]; +"233E" [ label="",shape="box",style="filled",color="grey" ]; +"25" [ label="3d475ea3aeca51b60212dd",shape="hexagon",style="filled",color="green" ]; +"235E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; +"26" [ label="966d271c22e75c7538",shape="hexagon",style="filled",color="green" ]; +"237E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"27" [ label="b630e1af6ae1997f0e8ba750",shape="hexagon",style="filled",color="green" ]; +"239E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; +"783E" [ label="499f6985db294c",shape="box",style="filled",color="grey" ]; +"28" [ label="ebd8ffc2ac3a90efb8af9",shape="hexagon",style="filled",color="green" ]; +"241E" [ label="1ebeec",shape="box",style="filled",color="grey" ]; +"791E" [ label="c0b727",shape="box",style="filled",color="grey" ]; +"29" [ label="69fdd1a1f4768c5efe7",shape="hexagon",style="filled",color="green" ]; +"243E" [ label="35b8742610",shape="box",style="filled",color="grey" ]; +"30" [ label="d93a80739fc1edb41a11b7294",shape="hexagon",style="filled",color="green" ]; +"245E" [ label="e03b8bc0435a",shape="box",style="filled",color="grey" ]; +"31" [ label="bf65cfddeb00ff847feae0c",shape="hexagon",style="filled",color="green" ]; +"247E" [ label="8df",shape="box",style="filled",color="grey" ]; +"32" [ label="916c686a1e82dba72524a",shape="hexagon",style="filled",color="green" ]; +"249E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; +"33" [ label="f496bcf0889b301d77819c",shape="hexagon",style="filled",color="green" ]; +"251E" [ label="f29dfb9",shape="box",style="filled",color="grey" ]; +"34" [ label="76889f7d35e",shape="hexagon",style="filled",color="green" ]; +"253E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; +"35" [ label="668d636002",shape="hexagon",style="filled",color="green" ]; +"255E" [ label="4379b5ed",shape="box",style="filled",color="grey" ]; +"36" [ label="e1e4c23db39d8bd633c3a",shape="hexagon",style="filled",color="green" ]; +"257E" [ label="1ed5d7f63b8c6",shape="box",style="filled",color="grey" ]; +"37" [ label="842bc5775657c1e0d67",shape="hexagon",style="filled",color="green" ]; +"259E" [ label="a387210a27b",shape="box",style="filled",color="grey" ]; +"38" [ label="e4e2f4e6d",shape="hexagon",style="filled",color="green" ]; +"261E" [ label="1f4f0fdf",shape="box",style="filled",color="grey" ]; +"39" [ label="04390dec6f1779353c07f5",shape="hexagon",style="filled",color="green" ]; +"263E" [ label="bac77c3f414a",shape="box",style="filled",color="grey" ]; +"40" [ label="69f2611acc42c36ed7cc",shape="hexagon",style="filled",color="green" ]; +"265E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"41" [ label="1562abef0d8241",shape="hexagon",style="filled",color="green" ]; +"267E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; +"42" [ label="e49aaa5cc4e44355d6a0",shape="hexagon",style="filled",color="green" ]; +"269E" [ label="cc3f63d",shape="box",style="filled",color="grey" ]; +"43" [ label="e8ebe1bf5f421c1223",shape="hexagon",style="filled",color="green" ]; +"271E" [ label="96325ea",shape="box",style="filled",color="grey" ]; +"44" [ label="2759e82e30d6d",shape="hexagon",style="filled",color="green" ]; +"273E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; +"45" [ label="23c1ec53358d237c1",shape="hexagon",style="filled",color="green" ]; +"275E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"46" [ label="5838586c293d455",shape="hexagon",style="filled",color="green" ]; +"277E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; +"47" [ label="f841118350a27b7ea29a9c9d",shape="hexagon",style="filled",color="green" ]; +"279E" [ label="69f4ecb77d",shape="box",style="filled",color="grey" ]; +"48" [ label="658d208447d8ec5d6de8",shape="hexagon",style="filled",color="green" ]; +"281E" [ label="f7b22b9640",shape="box",style="filled",color="grey" ]; +"49" [ label="11180ae7706510211bc4",shape="hexagon",style="filled",color="green" ]; +"283E" [ label="052bb6e3",shape="box",style="filled",color="grey" ]; +"50" [ label="5807acd8d58e006f43",shape="hexagon",style="filled",color="green" ]; +"285E" [ label="",shape="box",style="filled",color="grey" ]; +"51" [ label="fe4e848cb5291ee59a2",shape="hexagon",style="filled",color="green" ]; +"287E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; +"52" [ label="c4f31ea3844e12da27ad47c6",shape="hexagon",style="filled",color="green" ]; +"289E" [ label="fb16636aae",shape="box",style="filled",color="grey" ]; +"53" [ label="00cbeb87c182ca0785f",shape="hexagon",style="filled",color="green" ]; +"291E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; +"54" [ label="11f088bfd8",shape="hexagon",style="filled",color="green" ]; +"293E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; +"55" [ label="64a9ec24428099ad8ed82ba6",shape="hexagon",style="filled",color="green" ]; +"745E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; +"56" [ label="3c2a62e0e5e9f7",shape="hexagon",style="filled",color="green" ]; +"295E" [ label="ae32701",shape="box",style="filled",color="grey" ]; +"57" [ label="dd84fe6a65cfac7bca03ebd",shape="hexagon",style="filled",color="green" ]; +"297E" [ label="",shape="box",style="filled",color="grey" ]; +"58" [ label="b06bbfa920aa95dd",shape="hexagon",style="filled",color="green" ]; +"299E" [ label="07",shape="box",style="filled",color="grey" ]; +"59" [ label="6b5aaa4bdf44b2c898854",shape="hexagon",style="filled",color="green" ]; +"301E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; +"789E" [ label="3a0ff0",shape="box",style="filled",color="grey" ]; +"60" [ label="855d26296eda4eb7",shape="hexagon",style="filled",color="green" ]; +"303E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; +"61" [ label="e82f47b8d4949ba4af69b38cbc19",shape="hexagon",style="filled",color="green" ]; +"305E" [ label="b62cd1d0a0",shape="box",style="filled",color="grey" ]; +"62" [ label="86569bffb49adf6b3d0ebac",shape="hexagon",style="filled",color="green" ]; +"307E" [ label="660ffeb76fc59",shape="box",style="filled",color="grey" ]; +"63" [ label="a96e47ff37983425a3e452095",shape="hexagon",style="filled",color="green" ]; +"309E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"64" [ label="71a48d11b2e7e56b1df128bd",shape="hexagon",style="filled",color="green" ]; +"311E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; +"65" [ label="a0befe6dd1ca7b165786835",shape="hexagon",style="filled",color="green" ]; +"313E" [ label="3cfae",shape="box",style="filled",color="grey" ]; +"66" [ label="f33ec11db496f7bfcb024f",shape="hexagon",style="filled",color="green" ]; +"315E" [ label="71e6b",shape="box",style="filled",color="grey" ]; +"67" [ label="fe6be3206549f5b5564acde84783",shape="hexagon",style="filled",color="green" ]; +"317E" [ label="",shape="box",style="filled",color="grey" ]; +"68" [ label="e4dba079d5fcb1f165920a3bf",shape="hexagon",style="filled",color="green" ]; +"319E" [ label="",shape="box",style="filled",color="grey" ]; +"69" [ label="35dfbee3123dc389cba0b15",shape="hexagon",style="filled",color="green" ]; +"746E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; +"70" [ label="16c508ab98483d430bbe",shape="hexagon",style="filled",color="green" ]; +"321E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"71" [ label="9c9e2e0f2da8758e436c",shape="hexagon",style="filled",color="green" ]; +"327E" [ label="cd0d985a366cad7e",shape="box",style="filled",color="grey" ]; +"72" [ label="fb039d7a2a9fe73b5f468eba9",shape="hexagon",style="filled",color="green" ]; +"329E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"73" [ label="2ef949c4a39b",shape="hexagon",style="filled",color="green" ]; +"331E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; +"74" [ label="a9497e0757b0969bde707ed5",shape="hexagon",style="filled",color="green" ]; +"333E" [ label="541ab86a2e",shape="box",style="filled",color="grey" ]; +"75" [ label="230cc6bbc66b24eae94fa03d",shape="hexagon",style="filled",color="green" ]; +"335E" [ label="",shape="box",style="filled",color="grey" ]; +"76" [ label="1d163eac141def176461c",shape="hexagon",style="filled",color="green" ]; +"337E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; +"77" [ label="32979f8cf86",shape="hexagon",style="filled",color="green" ]; +"339E" [ label="a7e89580",shape="box",style="filled",color="grey" ]; +"78" [ label="37d80ae421dba4a70730338860",shape="hexagon",style="filled",color="green" ]; +"341E" [ label="",shape="box",style="filled",color="grey" ]; +"79" [ label="fbba7215e7c13173a60206",shape="hexagon",style="filled",color="green" ]; +"343E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; +"80" [ label="2dd8cc4d693415f93c0f8fc",shape="hexagon",style="filled",color="green" ]; +"345E" [ label="94da691e20e3",shape="box",style="filled",color="grey" ]; +"81" [ label="00880e6f50c765ebc1f85d3e9",shape="hexagon",style="filled",color="green" ]; +"347E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; +"82" [ label="ef13d45b1277ac9a0444adb",shape="hexagon",style="filled",color="green" ]; +"349E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; +"83" [ label="2573e1bf51f1b307f4640",shape="hexagon",style="filled",color="green" ]; +"351E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; +"84" [ label="162d8039483d8",shape="hexagon",style="filled",color="green" ]; +"353E" [ label="a8e9",shape="box",style="filled",color="grey" ]; +"85" [ label="f490de272a7f6e4af346d40",shape="hexagon",style="filled",color="green" ]; +"355E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; +"788E" [ label="391256c872",shape="box",style="filled",color="grey" ]; +"86" [ label="678bf739c344b9ad41da1",shape="hexagon",style="filled",color="green" ]; +"357E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; +"87" [ label="876d120b38b0e88817",shape="hexagon",style="filled",color="green" ]; +"359E" [ label="e5",shape="box",style="filled",color="grey" ]; +"88" [ label="503737b64d432c60d6ac557e0e6",shape="hexagon",style="filled",color="green" ]; +"361E" [ label="9937ccba1469",shape="box",style="filled",color="grey" ]; +"89" [ label="b36e0be6f67fc25286127456",shape="hexagon",style="filled",color="green" ]; +"363E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; +"90" [ label="4cc20a0b7651e486",shape="hexagon",style="filled",color="green" ]; +"365E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; +"91" [ label="08dade990b2282",shape="hexagon",style="filled",color="green" ]; +"367E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; +"92" [ label="f8128d574c356631b8a9",shape="hexagon",style="filled",color="green" ]; +"369E" [ label="",shape="box",style="filled",color="grey" ]; +"93" [ label="88a4f0337c2189c3fc7b31",shape="hexagon",style="filled",color="green" ]; +"729E" [ label="da0d7bbcf30",shape="box",style="filled",color="grey" ]; +"94" [ label="1b13908a9f0763c0ae54af9062080",shape="hexagon",style="filled",color="green" ]; +"371E" [ label="8b06a67a",shape="box",style="filled",color="grey" ]; +"95" [ label="e2a5d11499b7e",shape="hexagon",style="filled",color="green" ]; +"373E" [ label="66abc181ac4",shape="box",style="filled",color="grey" ]; +"96" [ label="90cc275011c2013c61eb11",shape="hexagon",style="filled",color="green" ]; +"375E" [ label="",shape="box",style="filled",color="grey" ]; +"97" [ label="1e003bfe8fc840df0163f4c",shape="hexagon",style="filled",color="green" ]; +"747E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"98" [ label="1927c743a0d440a5a0",shape="hexagon",style="filled",color="green" ]; +"377E" [ label="b12441ecff15fa12c",shape="box",style="filled",color="grey" ]; +"99" [ label="155d892827c33ed3cae3",shape="hexagon",style="filled",color="green" ]; +"379E" [ label="71e6b",shape="box",style="filled",color="grey" ]; +"100" [ label="9f24ba80192c339a64c0",shape="hexagon",style="filled",color="green" ]; +"381E" [ label="",shape="box",style="filled",color="grey" ]; +"101" [ label="3e814305b42beb41b8c706",shape="hexagon",style="filled",color="green" ]; +"383E" [ label="1c08373",shape="box",style="filled",color="grey" ]; +"102" [ label="eccfe5ff0af70fe9fbec8b2360f90",shape="hexagon",style="filled",color="green" ]; +"385E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; +"103" [ label="8fa622d9f842c5572a545ed72982",shape="hexagon",style="filled",color="green" ]; +"387E" [ label="4dccb",shape="box",style="filled",color="grey" ]; +"104" [ label="ad9142a65f5eab78b4ca5e",shape="hexagon",style="filled",color="green" ]; +"389E" [ label="f36cce089",shape="box",style="filled",color="grey" ]; +"105" [ label="20f234fdcd0e1fc50261ce8",shape="hexagon",style="filled",color="green" ]; +"391E" [ label="67219ef689f0146b544",shape="box",style="filled",color="grey" ]; +"106" [ label="e06cc38155ff6781cf944d745",shape="hexagon",style="filled",color="green" ]; +"393E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; +"107" [ label="cfdf1932665dcb4cd3c",shape="hexagon",style="filled",color="green" ]; +"395E" [ label="964b86fc1bba0e",shape="box",style="filled",color="grey" ]; +"108" [ label="6d4a4a5a5af91b895272c30",shape="hexagon",style="filled",color="green" ]; +"397E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; +"109" [ label="e0ad365c2fb444358201",shape="hexagon",style="filled",color="green" ]; +"399E" [ label="bb5e89c8963",shape="box",style="filled",color="grey" ]; +"110" [ label="b07bbdc8cca5985d4c4",shape="hexagon",style="filled",color="green" ]; +"401E" [ label="50023f6f88",shape="box",style="filled",color="grey" ]; +"111" [ label="df5dba74c75b228de48c",shape="hexagon",style="filled",color="green" ]; +"403E" [ label="7e493ee44b28",shape="box",style="filled",color="grey" ]; +"112" [ label="0b8694c9ef9b27b9c3d8",shape="hexagon",style="filled",color="green" ]; +"405E" [ label="2342b759c03",shape="box",style="filled",color="grey" ]; +"113" [ label="81e20155999fa64e0ae6fd",shape="hexagon",style="filled",color="green" ]; +"407E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; +"114" [ label="3ef07ae75d29a707",shape="hexagon",style="filled",color="green" ]; +"409E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; +"115" [ label="4a36db80f1ab1e97",shape="hexagon",style="filled",color="green" ]; +"411E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; +"116" [ label="16da5f1301b36df4df0f",shape="hexagon",style="filled",color="green" ]; +"413E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; +"117" [ label="6b3f3fa236bb90592d23a",shape="hexagon",style="filled",color="green" ]; +"415E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; +"118" [ label="f2a57e4d4f0cec516891e3",shape="hexagon",style="filled",color="green" ]; +"417E" [ label="bd2484",shape="box",style="filled",color="grey" ]; +"119" [ label="deb3089920548bf1ecb23f0d",shape="hexagon",style="filled",color="green" ]; +"419E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; +"120" [ label="bf01c8a262",shape="hexagon",style="filled",color="green" ]; +"421E" [ label="01",shape="box",style="filled",color="grey" ]; +"121" [ label="23dc3a52fed9c119610b5e8",shape="hexagon",style="filled",color="green" ]; +"423E" [ label="71e6b",shape="box",style="filled",color="grey" ]; +"122" [ label="aff7fc220edc93572bb2",shape="hexagon",style="filled",color="green" ]; +"748E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; +"123" [ label="78cc16f965adc5f712ea2372c6",shape="hexagon",style="filled",color="green" ]; +"425E" [ label="23ad1",shape="box",style="filled",color="grey" ]; +"124" [ label="5be631dff7b97697be7dc0a2f07f2",shape="hexagon",style="filled",color="green" ]; +"427E" [ label="",shape="box",style="filled",color="grey" ]; +"786E" [ label="421",shape="box",style="filled",color="grey" ]; +"125" [ label="48398d080dfcccced48da1980",shape="hexagon",style="filled",color="green" ]; +"431E" [ label="866808df",shape="box",style="filled",color="grey" ]; +"126" [ label="03716a2c341e5edaa31",shape="hexagon",style="filled",color="green" ]; +"433E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; +"127" [ label="ddfeabe456a9de5f5784",shape="hexagon",style="filled",color="green" ]; +"435E" [ label="aac615ae78",shape="box",style="filled",color="grey" ]; +"128" [ label="d550a7f392c787661aadd48",shape="hexagon",style="filled",color="green" ]; +"437E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; +"129" [ label="4c82921f4ad3f07066540",shape="hexagon",style="filled",color="green" ]; +"439E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; +"130" [ label="0bc7f8f513e0e74b270",shape="hexagon",style="filled",color="green" ]; +"441E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; +"131" [ label="3b1563a23eb9",shape="hexagon",style="filled",color="green" ]; +"443E" [ label="a8e9",shape="box",style="filled",color="grey" ]; +"132" [ label="be233fafa38d931d894",shape="hexagon",style="filled",color="green" ]; +"445E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; +"133" [ label="f906dc5244ee6a371f8",shape="hexagon",style="filled",color="green" ]; +"749E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; +"134" [ label="e7a887d88c2318beba51",shape="hexagon",style="filled",color="green" ]; +"447E" [ label="9d8988c0945d6",shape="box",style="filled",color="grey" ]; +"135" [ label="be6b73bd46a7a5183e8c91a",shape="hexagon",style="filled",color="green" ]; +"449E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; +"769E" [ label="444189d179b5db71fe",shape="box",style="filled",color="grey" ]; +"770E" [ label="1e1fbbe14ac24e0518",shape="box",style="filled",color="grey" ]; +"136" [ label="644f112bb0aa452ee7040a",shape="hexagon",style="filled",color="green" ]; +"451E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; +"137" [ label="010957669f3770aac",shape="hexagon",style="filled",color="green" ]; +"453E" [ label="78",shape="box",style="filled",color="grey" ]; +"138" [ label="0a185946ee443342b07d8e1",shape="hexagon",style="filled",color="green" ]; +"455E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; +"139" [ label="f66fe4df3d189e69ce10c9c",shape="hexagon",style="filled",color="green" ]; +"457E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; +"140" [ label="247e407f45b353f8",shape="hexagon",style="filled",color="green" ]; +"459E" [ label="",shape="box",style="filled",color="grey" ]; +"141" [ label="84907547f36d0ff7",shape="hexagon",style="filled",color="green" ]; +"461E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; +"142" [ label="805004328dad9d315d",shape="hexagon",style="filled",color="green" ]; +"463E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; +"143" [ label="4f0cbd3fbf0cb1e8c",shape="hexagon",style="filled",color="green" ]; +"465E" [ label="403126",shape="box",style="filled",color="grey" ]; +"144" [ label="4869e993f2bb10f",shape="hexagon",style="filled",color="green" ]; +"467E" [ label="ff",shape="box",style="filled",color="grey" ]; +"145" [ label="665b76844ff78fc2cf66ca2",shape="hexagon",style="filled",color="green" ]; +"469E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; +"146" [ label="3f16509139c7dad5163b91799",shape="hexagon",style="filled",color="green" ]; +"471E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; +"147" [ label="01db23a60422ba93a68611cc0",shape="hexagon",style="filled",color="green" ]; +"473E" [ label="",shape="box",style="filled",color="grey" ]; +"148" [ label="46125fcc583c0f494a3a1d3",shape="hexagon",style="filled",color="green" ]; +"475E" [ label="db6c4213a717bc",shape="box",style="filled",color="grey" ]; +"149" [ label="731857fe189fb398e80a0594",shape="hexagon",style="filled",color="green" ]; +"477E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; +"150" [ label="6fb7a84e370ef70feac5cb",shape="hexagon",style="filled",color="green" ]; +"479E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; +"151" [ label="e343cea291b79a2ed4e",shape="hexagon",style="filled",color="green" ]; +"481E" [ label="88d8b220746882d",shape="box",style="filled",color="grey" ]; +"152" [ label="5f2592b20f13356b7fc8b42",shape="hexagon",style="filled",color="green" ]; +"483E" [ label="",shape="box",style="filled",color="grey" ]; +"153" [ label="275a0407e33e9b8aa9cdd051",shape="hexagon",style="filled",color="green" ]; +"731E" [ label="",shape="box",style="filled",color="grey" ]; +"154" [ label="011d119375cf494ca2fa8d59",shape="hexagon",style="filled",color="green" ]; +"750E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"155" [ label="173fd00917644f0f1f3e3",shape="hexagon",style="filled",color="green" ]; +"485E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; +"156" [ label="c72df69b40156a3254",shape="hexagon",style="filled",color="green" ]; +"487E" [ label="fff03efcd",shape="box",style="filled",color="grey" ]; +"157" [ label="6c632ad9c42228bb337",shape="hexagon",style="filled",color="green" ]; +"489E" [ label="eb8",shape="box",style="filled",color="grey" ]; +"158" [ label="bbb13dc62adf2de2a42b6",shape="hexagon",style="filled",color="green" ]; +"491E" [ label="69ce90c9b2",shape="box",style="filled",color="grey" ]; +"159" [ label="6282bc21f6",shape="hexagon",style="filled",color="green" ]; +"495E" [ label="de34214b4c258c9333ec3",shape="box",style="filled",color="grey" ]; +"160" [ label="71cf45dd4e91bcca945137b40e",shape="hexagon",style="filled",color="green" ]; +"499E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; +"161" [ label="a3b6df27179b175c88fa4c9cf9f",shape="hexagon",style="filled",color="green" ]; +"501E" [ label="6577",shape="box",style="filled",color="grey" ]; +"162" [ label="284f14a259991806654e74",shape="hexagon",style="filled",color="green" ]; +"503E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; +"163" [ label="a7c99ccf6ddf6f5ebbe",shape="hexagon",style="filled",color="green" ]; +"505E" [ label="c4fd8",shape="box",style="filled",color="grey" ]; +"164" [ label="c32d2697e8",shape="hexagon",style="filled",color="green" ]; +"507E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; +"165" [ label="d12bd75c24b110ef90cdd35d3",shape="hexagon",style="filled",color="green" ]; +"509E" [ label="0668",shape="box",style="filled",color="grey" ]; +"166" [ label="1c07453d584f3d14b1876fdb",shape="hexagon",style="filled",color="green" ]; +"511E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; +"167" [ label="f713a8b311ffa05ce3683ad10",shape="hexagon",style="filled",color="green" ]; +"513E" [ label="30d6138b63eb",shape="box",style="filled",color="grey" ]; +"168" [ label="3cdc90c57243373efaba65a",shape="hexagon",style="filled",color="green" ]; +"515E" [ label="fa2afbd869",shape="box",style="filled",color="grey" ]; +"169" [ label="e3bdbca0e2256fffa8a59018",shape="hexagon",style="filled",color="green" ]; +"517E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"170" [ label="75ba8d840070942eb4e737849",shape="hexagon",style="filled",color="green" ]; +"519E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"171" [ label="fbdc3ca37406f66635c8b226e",shape="hexagon",style="filled",color="green" ]; +"521E" [ label="8cbcf5cb5",shape="box",style="filled",color="grey" ]; +"172" [ label="40b49a5a9bb256c7a3286e56",shape="hexagon",style="filled",color="green" ]; +"523E" [ label="f72564578be",shape="box",style="filled",color="grey" ]; +"173" [ label="3b2f08d52e4bca3f9ca7bbbd6",shape="hexagon",style="filled",color="green" ]; +"525E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"174" [ label="4a38abc630c82b0c48dfbf5271",shape="hexagon",style="filled",color="green" ]; +"527E" [ label="f0bd1521",shape="box",style="filled",color="grey" ]; +"175" [ label="2d7b7fb6c9ad6821752651f7",shape="hexagon",style="filled",color="green" ]; +"529E" [ label="47b2da3d",shape="box",style="filled",color="grey" ]; +"176" [ label="910b00285f11bb90d0a15641",shape="hexagon",style="filled",color="green" ]; +"531E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"177" [ label="24431c3eb075102f07cc2c1be",shape="hexagon",style="filled",color="green" ]; +"533E" [ label="",shape="box",style="filled",color="grey" ]; +"178" [ label="07f8a9e55a16beddb3c9153b0",shape="hexagon",style="filled",color="green" ]; +"535E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; +"179" [ label="c1c30f30d40c4f1f84924622f",shape="hexagon",style="filled",color="green" ]; +"537E" [ label="c5d5be3942",shape="box",style="filled",color="grey" ]; +"180" [ label="86276bb1e23f2c7ffcbe82a0",shape="hexagon",style="filled",color="green" ]; +"539E" [ label="0f940646",shape="box",style="filled",color="grey" ]; +"181" [ label="f78e145a127014eb43345a0c",shape="hexagon",style="filled",color="green" ]; +"541E" [ label="d370c12dbc",shape="box",style="filled",color="grey" ]; +"182" [ label="a27037332d9fa5c43bcfe94c0",shape="hexagon",style="filled",color="green" ]; +"543E" [ label="80874aa8",shape="box",style="filled",color="grey" ]; +"183" [ label="c29ce10bb8d19b498355aa04",shape="hexagon",style="filled",color="green" ]; +"545E" [ label="1c08373",shape="box",style="filled",color="grey" ]; +"184" [ label="4f8c642b53c349c687534bda35db",shape="hexagon",style="filled",color="green" ]; +"547E" [ label="46969c4",shape="box",style="filled",color="grey" ]; +"185" [ label="30cc206b1878485",shape="hexagon",style="filled",color="green" ]; +"549E" [ label="23ad1",shape="box",style="filled",color="grey" ]; +"186" [ label="5d69639a5e3bdd3d",shape="hexagon",style="filled",color="green" ]; +"551E" [ label="6139fa6adc88d",shape="box",style="filled",color="grey" ]; +"187" [ label="b656f0ed2202b8e46eb",shape="hexagon",style="filled",color="green" ]; +"553E" [ label="f6e6236b48bc3",shape="box",style="filled",color="grey" ]; +"188" [ label="3b566eaa70ed401479d43a9",shape="hexagon",style="filled",color="green" ]; +"555E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; +"189" [ label="d6125ef42bd9958",shape="hexagon",style="filled",color="green" ]; +"557E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; +"190" [ label="dd12f26f8d9bb55",shape="hexagon",style="filled",color="green" ]; +"559E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; +"191" [ label="ea890ccca2f7c2107351",shape="hexagon",style="filled",color="green" ]; +"561E" [ label="eb8",shape="box",style="filled",color="grey" ]; +"192" [ label="84e4f1c582427a98d7b",shape="hexagon",style="filled",color="green" ]; +"563E" [ label="eb8",shape="box",style="filled",color="grey" ]; +"193" [ label="d378760b814eaecb6efe636e0efc4",shape="hexagon",style="filled",color="green" ]; +"565E" [ label="81bcc35f82891",shape="box",style="filled",color="grey" ]; +"194" [ label="f722890f70a32dce3baff371a",shape="hexagon",style="filled",color="green" ]; +"567E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; +"195" [ label="666f11bb45c3a8dcf26e1ed79",shape="hexagon",style="filled",color="green" ]; +"569E" [ label="c90f755c8b6612d",shape="box",style="filled",color="grey" ]; +"196" [ label="91ecbe29a71f00ed5a3",shape="hexagon",style="filled",color="green" ]; +"571E" [ label="0a963fef9",shape="box",style="filled",color="grey" ]; +"197" [ label="30c3f3bf8463d3843dc57d8e98",shape="hexagon",style="filled",color="green" ]; +"573E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; +"198" [ label="8ea965ab6ee8dedb6c3333e9",shape="hexagon",style="filled",color="green" ]; +"575E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; +"199" [ label="3eecb304bab2136a76deda",shape="hexagon",style="filled",color="green" ]; +"577E" [ label="8df",shape="box",style="filled",color="grey" ]; +"200" [ label="d886e4b76537a99bc71b8a9331c94",shape="hexagon",style="filled",color="green" ]; +"579E" [ label="1172dca23",shape="box",style="filled",color="grey" ]; +"201" [ label="dcc5d5e9d6c4e",shape="hexagon",style="filled",color="green" ]; +"581E" [ label="a8e9",shape="box",style="filled",color="grey" ]; +"202" [ label="8292af691429f8d9ed481ff71ffd",shape="hexagon",style="filled",color="green" ]; +"583E" [ label="212af4",shape="box",style="filled",color="grey" ]; +"203" [ label="12fcb26b3de00ef98719c2ca",shape="hexagon",style="filled",color="green" ]; +"585E" [ label="",shape="box",style="filled",color="grey" ]; +"204" [ label="a141a557a60912051f3c135",shape="hexagon",style="filled",color="green" ]; +"587E" [ label="",shape="box",style="filled",color="grey" ]; +"205" [ label="64eeeddfc34489ff396",shape="hexagon",style="filled",color="green" ]; +"751E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"206" [ label="f5d636e14a6cd716362158d",shape="hexagon",style="filled",color="green" ]; +"589E" [ label="32c958c9997",shape="box",style="filled",color="grey" ]; +"207" [ label="84e4978afc069d5a1aecbf2b",shape="hexagon",style="filled",color="green" ]; +"593E" [ label="56caa96d171a9ac2da7c",shape="box",style="filled",color="grey" ]; +"208" [ label="52a6c2063bccd83110c32",shape="hexagon",style="filled",color="green" ]; +"597E" [ label="",shape="box",style="filled",color="grey" ]; +"209" [ label="46f754ea06f070dbc023e571a876",shape="hexagon",style="filled",color="green" ]; +"599E" [ label="ffccaa9e3",shape="box",style="filled",color="grey" ]; +"210" [ label="c10cb9baf4dcb43e24",shape="hexagon",style="filled",color="green" ]; +"601E" [ label="ac6e99186",shape="box",style="filled",color="grey" ]; +"211" [ label="3dafe1619016463f521f",shape="hexagon",style="filled",color="green" ]; +"603E" [ label="b9",shape="box",style="filled",color="grey" ]; +"212" [ label="0f5db6ce12751ddcc64e",shape="hexagon",style="filled",color="green" ]; +"605E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; +"213" [ label="34c8c8dc0f6e41c7e7b2",shape="hexagon",style="filled",color="green" ]; +"607E" [ label="2832ed5cea6",shape="box",style="filled",color="grey" ]; +"214" [ label="0a49c95f107c0aa57c9b5748",shape="hexagon",style="filled",color="green" ]; +"609E" [ label="",shape="box",style="filled",color="grey" ]; +"215" [ label="3b4fdad8e0429d112",shape="hexagon",style="filled",color="green" ]; +"611E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"216" [ label="17dafa5ebaafd48440e3",shape="hexagon",style="filled",color="green" ]; +"613E" [ label="b5f038f79a3",shape="box",style="filled",color="grey" ]; +"217" [ label="f4c69e5e212f89348122e8",shape="hexagon",style="filled",color="green" ]; +"615E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; +"218" [ label="4f2e020854dfacce46a12",shape="hexagon",style="filled",color="green" ]; +"617E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; +"219" [ label="6448451ac2ceade90715378b",shape="hexagon",style="filled",color="green" ]; +"619E" [ label="",shape="box",style="filled",color="grey" ]; +"220" [ label="7d7b14baa649330",shape="hexagon",style="filled",color="green" ]; +"621E" [ label="77d145b32328880440c7a",shape="box",style="filled",color="grey" ]; +"221" [ label="d7c27cc6f7b02a31eb64d",shape="hexagon",style="filled",color="green" ]; +"623E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; +"222" [ label="8f5a69ece1",shape="hexagon",style="filled",color="green" ]; +"752E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; +"223" [ label="eccf7c722ddf",shape="hexagon",style="filled",color="green" ]; +"625E" [ label="df61d5f5fc",shape="box",style="filled",color="grey" ]; +"224" [ label="86633c26be93ada8b",shape="hexagon",style="filled",color="green" ]; +"627E" [ label="08500a6044",shape="box",style="filled",color="grey" ]; +"225" [ label="3f9ddf1ffbc0d38b",shape="hexagon",style="filled",color="green" ]; +"629E" [ label="07",shape="box",style="filled",color="grey" ]; +"226" [ label="e33792703",shape="hexagon",style="filled",color="green" ]; +"631E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; +"227" [ label="293a225dc56dd1e0564e6bb",shape="hexagon",style="filled",color="green" ]; +"633E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; +"228" [ label="57c77c341f94afddef07e6",shape="hexagon",style="filled",color="green" ]; +"635E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; +"229" [ label="3bbfc7bfdbbb1ba1bfad7517",shape="hexagon",style="filled",color="green" ]; +"637E" [ label="",shape="box",style="filled",color="grey" ]; +"230" [ label="a7167d5eb5408b3839903",shape="hexagon",style="filled",color="green" ]; +"639E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; +"231" [ label="34d7bb6af4fcd8d630de72500c8",shape="hexagon",style="filled",color="green" ]; +"641E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; +"232" [ label="8e69341faa4489",shape="hexagon",style="filled",color="green" ]; +"643E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"233" [ label="459236f07c73814faf5",shape="hexagon",style="filled",color="green" ]; +"645E" [ label="18083a711d",shape="box",style="filled",color="grey" ]; +"234" [ label="c71aa521578164debd0c5",shape="hexagon",style="filled",color="green" ]; +"647E" [ label="78",shape="box",style="filled",color="grey" ]; +"235" [ label="a5520019b8a73bc141b5fd416a",shape="hexagon",style="filled",color="green" ]; +"649E" [ label="3219b6b71443",shape="box",style="filled",color="grey" ]; +"236" [ label="6c89dc59ee7aaebbbd6bb64",shape="hexagon",style="filled",color="green" ]; +"651E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; +"237" [ label="a9a36ef02f",shape="hexagon",style="filled",color="green" ]; +"653E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; +"238" [ label="3db761b596844f133c",shape="hexagon",style="filled",color="green" ]; +"655E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; +"239" [ label="383db224d7508ef072bea21d0",shape="hexagon",style="filled",color="green" ]; +"657E" [ label="975fedfb64df",shape="box",style="filled",color="grey" ]; +"240" [ label="8e307415fb435445ced7",shape="hexagon",style="filled",color="green" ]; +"659E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; +"241" [ label="aff6d7896e0e142bbc3e78",shape="hexagon",style="filled",color="green" ]; +"661E" [ label="d2498",shape="box",style="filled",color="grey" ]; +"242" [ label="e153c6e676c7369b285b4e9033a",shape="hexagon",style="filled",color="green" ]; +"663E" [ label="",shape="box",style="filled",color="grey" ]; +"243" [ label="f3c4311de0e931f08c232b",shape="hexagon",style="filled",color="green" ]; +"665E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; +"244" [ label="0c72a426929600000f5",shape="hexagon",style="filled",color="green" ]; +"667E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; +"245" [ label="38fa61352f5086d2cb51",shape="hexagon",style="filled",color="green" ]; +"669E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; +"246" [ label="ad1dd724f1c3e",shape="hexagon",style="filled",color="green" ]; +"671E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; +"247" [ label="11bb8ed3ae227d3acefc",shape="hexagon",style="filled",color="green" ]; +"673E" [ label="eb8",shape="box",style="filled",color="grey" ]; +"248" [ label="f2c7b3bb4d44f977d0ab8a42351",shape="hexagon",style="filled",color="green" ]; +"675E" [ label="",shape="box",style="filled",color="grey" ]; +"249" [ label="51e045ca826077ae765",shape="hexagon",style="filled",color="green" ]; +"679E" [ label="e842",shape="box",style="filled",color="grey" ]; +"250" [ label="aa0adc8978020629574",shape="hexagon",style="filled",color="green" ]; +"753E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; +"251" [ label="3b6b2c549de670d7bf5fc0ee",shape="hexagon",style="filled",color="green" ]; +"681E" [ label="",shape="box",style="filled",color="grey" ]; +"252" [ label="5eea496cc301b2a9721",shape="hexagon",style="filled",color="green" ]; +"683E" [ label="",shape="box",style="filled",color="grey" ]; +"253" [ label="bfc6564cbdeeffac00a141",shape="hexagon",style="filled",color="green" ]; +"685E" [ label="3b0a8a1c2e5050bd",shape="box",style="filled",color="grey" ]; +"254" [ label="c360aaeb167487c9578a8f",shape="hexagon",style="filled",color="green" ]; +"687E" [ label="d",shape="box",style="filled",color="grey" ]; +"255" [ label="39d025b265f9790490781cb201",shape="hexagon",style="filled",color="green" ]; +"689E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; +"256" [ label="b4ce21e0a3df1d097277d6",shape="hexagon",style="filled",color="green" ]; +"691E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; +"257" [ label="8bdb6a91c6dee925b557c705b3",shape="hexagon",style="filled",color="green" ]; +"693E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; +"258" [ label="ac487676a04e4",shape="hexagon",style="filled",color="green" ]; +"695E" [ label="a8e9",shape="box",style="filled",color="grey" ]; +"259" [ label="18115fa32ff1cb99",shape="hexagon",style="filled",color="green" ]; +"697E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; +"260" [ label="b7b899dc8bc6a32b28cb098fa16",shape="hexagon",style="filled",color="green" ]; +"699E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; +"261" [ label="b69e426d974e1907e88",shape="hexagon",style="filled",color="green" ]; +"703E" [ label="e842",shape="box",style="filled",color="grey" ]; +"262" [ label="60d0128bdb61ae40e98638bd1391",shape="hexagon",style="filled",color="green" ]; +"705E" [ label="23ad1",shape="box",style="filled",color="grey" ]; +"264" [ label="8fb60d769e4c387",shape="hexagon",style="filled",color="green" ]; +"709E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; +"265" [ label="e1fa7f549e5a0893bb42da5",shape="hexagon",style="filled",color="green" ]; +"711E" [ label="6a3c6921b0aeceda3",shape="box",style="filled",color="grey" ]; +"266" [ label="a77622f2ff77ffeeb2",shape="hexagon",style="filled",color="green" ]; +"713E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; +"267" [ label="30d9d350943c0e3ff7594b50",shape="hexagon",style="filled",color="green" ]; +"715E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; +"268" [ label="89ced1a7906d58d687d5a04",shape="hexagon",style="filled",color="green" ]; +"717E" [ label="c0174bbe7ae8",shape="box",style="filled",color="grey" ]; +"269" [ label="1de26f6b12b0d292f94184",shape="hexagon",style="filled",color="green" ]; +"719E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; +"270" [ label="26fa7360ab81be9d4434a",shape="hexagon",style="filled",color="green" ]; +"721E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; +"272" [ label="4a9d79c960b8d33e39251e5f66",shape="hexagon" ]; +"34E" [ label="330342f283ef2",shape="box",style="filled",color="grey" ]; +"252E" [ label="3dafb9a29c00",shape="box",style="filled",color="grey" ]; +"436E" [ label="8d5137b16a",shape="box",style="filled",color="grey" ]; +"274" [ label="10a7d61c201c67a5e78542807cd",shape="hexagon" ]; +"59E" [ label="ef6361295eba07",shape="box",style="filled",color="grey" ]; +"500E" [ label="a8f0fe2eb7bc1471",shape="box",style="filled",color="grey" ]; +"720E" [ label="cfff3acd8e9d",shape="box",style="filled",color="grey" ]; +"275" [ label="f8ff39eab120851f143bf19",shape="hexagon" ]; +"98E" [ label="4e3cfd27a",shape="box",style="filled",color="grey" ]; +"278" [ label="4995c71223c9f6067324d387a2",shape="hexagon" ]; +"35E" [ label="57948adb5dead",shape="box",style="filled",color="grey" ]; +"488E" [ label="a738ba39",shape="box",style="filled",color="grey" ]; +"598E" [ label="be7d637c50c",shape="box",style="filled",color="grey" ]; +"604E" [ label="8d52f183ec",shape="box",style="filled",color="grey" ]; +"628E" [ label="cef12b6",shape="box",style="filled",color="grey" ]; +"279" [ label="b9ae94e6935503603341ecf4",shape="hexagon" ]; +"99E" [ label="14a3c17f3d",shape="box",style="filled",color="grey" ]; +"280" [ label="fd28c194a46fde909b019c52f",shape="hexagon" ]; +"242E" [ label="9fe65061641",shape="box",style="filled",color="grey" ]; +"270E" [ label="34d06d1ed6",shape="box",style="filled",color="grey" ]; +"272E" [ label="713db1c1",shape="box",style="filled",color="grey" ]; +"284E" [ label="90dccb18c0",shape="box",style="filled",color="grey" ]; +"286E" [ label="e17fea65",shape="box",style="filled",color="grey" ]; +"288E" [ label="aebb7b91b",shape="box",style="filled",color="grey" ]; +"586E" [ label="4348f3abcb7716",shape="box",style="filled",color="grey" ]; +"763E" [ label="b082f7a5ff",shape="box",style="filled",color="grey" ]; +"281" [ label="7c0ab977f5a3c4ab6d625f5033",shape="hexagon" ]; +"45E" [ label="20949455f573f",shape="box",style="filled",color="grey" ]; +"470E" [ label="c338481d79773",shape="box",style="filled",color="grey" ]; +"670E" [ label="e1d01ef89f",shape="box",style="filled",color="grey" ]; +"722E" [ label="c4507c22d19",shape="box",style="filled",color="grey" ]; +"282" [ label="7e0b91491c8c8566892cd9a0889",shape="hexagon" ]; +"103E" [ label="de9efa12873949",shape="box",style="filled",color="grey" ]; +"283" [ label="d58478d9c273ad4f4b2e091324",shape="hexagon" ]; +"165E" [ label="1a220eb692c",shape="box",style="filled",color="grey" ]; +"284" [ label="8be0efdd94a6383e87fbfded4f",shape="hexagon" ]; +"39E" [ label="c8a6c26d4fd9f",shape="box",style="filled",color="grey" ]; +"224E" [ label="8cbae42a3900",shape="box",style="filled",color="grey" ]; +"268E" [ label="fc73",shape="box",style="filled",color="grey" ]; +"632E" [ label="",shape="box",style="filled",color="grey" ]; +"710E" [ label="102f1",shape="box",style="filled",color="grey" ]; +"285" [ label="3aeb78ea51020a44f2d2615436dae",shape="hexagon" ]; +"53E" [ label="96deede0c6b44119",shape="box",style="filled",color="grey" ]; +"286" [ label="6bbd5b422edb8e358dcc20eecf9",shape="hexagon" ]; +"38E" [ label="4f2de229621272",shape="box",style="filled",color="grey" ]; +"166E" [ label="d495de0b35f6",shape="box",style="filled",color="grey" ]; +"288" [ label="4856000a6802ddfc121ef40432297",shape="hexagon",style="filled",color="#ff0000" ]; +"40E" [ label="04904a458422a5b9",shape="box",style="filled",color="grey" ]; +"218E" [ label="8cd4d",shape="box",style="filled",color="grey" ]; +"244E" [ label="",shape="box",style="filled",color="grey" ]; +"246E" [ label="9be88247",shape="box",style="filled",color="grey" ]; +"258E" [ label="4f05b",shape="box",style="filled",color="grey" ]; +"290E" [ label="8b092",shape="box",style="filled",color="grey" ]; +"292E" [ label="c3bbf4",shape="box",style="filled",color="grey" ]; +"308E" [ label="6331b3f",shape="box",style="filled",color="grey" ]; +"318E" [ label="",shape="box",style="filled",color="grey" ]; +"388E" [ label="3711",shape="box",style="filled",color="grey" ]; +"472E" [ label="c5255d",shape="box",style="filled",color="grey" ]; +"478E" [ label="5c6a2",shape="box",style="filled",color="grey" ]; +"566E" [ label="51ec95518d1b3",shape="box",style="filled",color="grey" ]; +"570E" [ label="82a65ed4b69",shape="box",style="filled",color="grey" ]; +"574E" [ label="05fed5e",shape="box",style="filled",color="grey" ]; +"608E" [ label="bf",shape="box",style="filled",color="grey" ]; +"614E" [ label="ce",shape="box",style="filled",color="grey" ]; +"658E" [ label="1a830d9f",shape="box",style="filled",color="grey" ]; +"664E" [ label="",shape="box",style="filled",color="grey" ]; +"682E" [ label="",shape="box",style="filled",color="grey" ]; +"289" [ label="2e31175cbd52fcd08360fe86d20",shape="hexagon" ]; +"41E" [ label="4ad5d68f07981a",shape="box",style="filled",color="grey" ]; +"636E" [ label="51192117f9b4",shape="box",style="filled",color="grey" ]; +"642E" [ label="6bf214d9e7fa5f2df",shape="box",style="filled",color="grey" ]; +"690E" [ label="558d8534f92fddfe",shape="box",style="filled",color="grey" ]; +"700E" [ label="6819fd5a6cdd280dd",shape="box",style="filled",color="grey" ]; +"290" [ label="3aa0ce5efcf79bc3ecced1886e89",shape="hexagon" ]; +"56E" [ label="ff9d64ddf49a20f",shape="box",style="filled",color="grey" ]; +"264E" [ label="6c93f24516f01d",shape="box",style="filled",color="grey" ]; +"510E" [ label="32b98f11f3d01d6",shape="box",style="filled",color="grey" ]; +"718E" [ label="8f7c875500073",shape="box",style="filled",color="grey" ]; +"291" [ label="7c1767485953d9c2",shape="hexagon" ]; +"66E" [ label="086",shape="box",style="filled",color="grey" ]; +"76E" [ label="",shape="box",style="filled",color="grey" ]; +"610E" [ label="450d3a2d49cbfd",shape="box",style="filled",color="grey" ]; +"292" [ label="9c1305d59c37e9be9f13d7d049c",shape="hexagon" ]; +"73E" [ label="817",shape="box",style="filled",color="grey" ]; +"293" [ label="efe092824916a5637ee35d439589",shape="hexagon" ]; +"49E" [ label="",shape="box",style="filled",color="grey" ]; +"214E" [ label="",shape="box",style="filled",color="grey" ]; +"216E" [ label="",shape="box",style="filled",color="grey" ]; +"236E" [ label="",shape="box",style="filled",color="grey" ]; +"278E" [ label="",shape="box",style="filled",color="grey" ]; +"358E" [ label="",shape="box",style="filled",color="grey" ]; +"398E" [ label="",shape="box",style="filled",color="grey" ]; +"400E" [ label="",shape="box",style="filled",color="grey" ]; +"402E" [ label="",shape="box",style="filled",color="grey" ]; +"404E" [ label="",shape="box",style="filled",color="grey" ]; +"406E" [ label="",shape="box",style="filled",color="grey" ]; +"408E" [ label="",shape="box",style="filled",color="grey" ]; +"412E" [ label="",shape="box",style="filled",color="grey" ]; +"438E" [ label="",shape="box",style="filled",color="grey" ]; +"448E" [ label="",shape="box",style="filled",color="grey" ]; +"476E" [ label="",shape="box",style="filled",color="grey" ]; +"504E" [ label="",shape="box",style="filled",color="grey" ]; +"552E" [ label="",shape="box",style="filled",color="grey" ]; +"634E" [ label="",shape="box",style="filled",color="grey" ]; +"768E" [ label="",shape="box",style="filled",color="grey" ]; +"295" [ label="70815f0352b43dc1562133ab6eb",shape="hexagon",style="filled",color="#A52A2A" ]; +"44E" [ label="ef2d4636934472",shape="box",style="filled",color="grey" ]; +"92E" [ label="22bd92e302816",shape="box",style="filled",color="grey" ]; +"250E" [ label="74e86",shape="box",style="filled",color="grey" ]; +"316E" [ label="",shape="box",style="filled",color="grey" ]; +"380E" [ label="",shape="box",style="filled",color="grey" ]; +"424E" [ label="c",shape="box",style="filled",color="grey" ]; +"442E" [ label="a5a",shape="box",style="filled",color="grey" ]; +"446E" [ label="bce",shape="box",style="filled",color="grey" ]; +"454E" [ label="",shape="box",style="filled",color="grey" ]; +"460E" [ label="",shape="box",style="filled",color="grey" ]; +"462E" [ label="",shape="box",style="filled",color="grey" ]; +"648E" [ label="",shape="box",style="filled",color="grey" ]; +"656E" [ label="e9",shape="box",style="filled",color="grey" ]; +"666E" [ label="b701e7",shape="box",style="filled",color="grey" ]; +"692E" [ label="f2e7cc",shape="box",style="filled",color="grey" ]; +"712E" [ label="8a9eb2806b0aa",shape="box",style="filled",color="grey" ]; +"296" [ label="e287d497450664a4c0f4efc338",shape="hexagon",style="filled",color="#ff0000" ]; +"47E" [ label="06eff1db45cdf",shape="box",style="filled",color="grey" ]; +"330E" [ label="c0f34a600",shape="box",style="filled",color="grey" ]; +"514E" [ label="bd7aca295ca",shape="box",style="filled",color="grey" ]; +"516E" [ label="0da9135",shape="box",style="filled",color="grey" ]; +"518E" [ label="fe821bce",shape="box",style="filled",color="grey" ]; +"520E" [ label="e64f22a31",shape="box",style="filled",color="grey" ]; +"522E" [ label="46e412a3",shape="box",style="filled",color="grey" ]; +"526E" [ label="99da1f8a5",shape="box",style="filled",color="grey" ]; +"528E" [ label="0f167280",shape="box",style="filled",color="grey" ]; +"530E" [ label="82d201",shape="box",style="filled",color="grey" ]; +"532E" [ label="1d529eb4",shape="box",style="filled",color="grey" ]; +"534E" [ label="",shape="box",style="filled",color="grey" ]; +"536E" [ label="bf141dbce",shape="box",style="filled",color="grey" ]; +"538E" [ label="e3fd0c7b3",shape="box",style="filled",color="grey" ]; +"540E" [ label="c96cb3",shape="box",style="filled",color="grey" ]; +"542E" [ label="0fabab47",shape="box",style="filled",color="grey" ]; +"544E" [ label="1b82200",shape="box",style="filled",color="grey" ]; +"297" [ label="2ced414a91575a48f2dd29a",shape="hexagon" ]; +"46E" [ label="85221d5e9e",shape="box",style="filled",color="grey" ]; +"93E" [ label="97a7eea3f",shape="box",style="filled",color="grey" ]; +"206E" [ label="4d22e1",shape="box",style="filled",color="grey" ]; +"426E" [ label="e65185ca",shape="box",style="filled",color="grey" ]; +"550E" [ label="",shape="box",style="filled",color="grey" ]; +"706E" [ label="a9012b7bb5",shape="box",style="filled",color="grey" ]; +"298" [ label="38f162cf917ce7298663a1f1c607",shape="hexagon" ]; +"36E" [ label="a031c9192ae8e75",shape="box",style="filled",color="grey" ]; +"95E" [ label="062fc905b9eb35",shape="box",style="filled",color="grey" ]; +"364E" [ label="c8fc17180bea86",shape="box",style="filled",color="grey" ]; +"394E" [ label="09e64744536c5e1",shape="box",style="filled",color="grey" ]; +"420E" [ label="af4a1fac3e2076",shape="box",style="filled",color="grey" ]; +"456E" [ label="238805e2194c3",shape="box",style="filled",color="grey" ]; +"624E" [ label="73e6ed83012",shape="box",style="filled",color="grey" ]; +"299" [ label="549fa15d68f0b3bee6192f888cd8",shape="hexagon" ]; +"48E" [ label="d17f8f4eeb8e63d",shape="box",style="filled",color="grey" ]; +"168E" [ label="cca7040e47789",shape="box",style="filled",color="grey" ]; +"260E" [ label="47ebc3f17",shape="box",style="filled",color="grey" ]; +"282E" [ label="cf5a6049ad",shape="box",style="filled",color="grey" ]; +"554E" [ label="2a47a6a27",shape="box",style="filled",color="grey" ]; +"590E" [ label="eff3468631dd4",shape="box",style="filled",color="grey" ]; +"767E" [ label="efb52b499303115c33fd",shape="box",style="filled",color="grey" ]; +"300" [ label="8593dcf973b110d00cecdc1e756",shape="hexagon",style="filled",color="#ff7f00" ]; +"62E" [ label="472a156cf2b55f",shape="box",style="filled",color="grey" ]; +"190E" [ label="647",shape="box",style="filled",color="grey" ]; +"226E" [ label="",shape="box",style="filled",color="grey" ]; +"238E" [ label="8a",shape="box",style="filled",color="grey" ]; +"254E" [ label="",shape="box",style="filled",color="grey" ]; +"256E" [ label="",shape="box",style="filled",color="grey" ]; +"262E" [ label="",shape="box",style="filled",color="grey" ]; +"266E" [ label="e8b",shape="box",style="filled",color="grey" ]; +"274E" [ label="",shape="box",style="filled",color="grey" ]; +"276E" [ label="f",shape="box",style="filled",color="grey" ]; +"294E" [ label="",shape="box",style="filled",color="grey" ]; +"296E" [ label="",shape="box",style="filled",color="grey" ]; +"310E" [ label="1b34fb150",shape="box",style="filled",color="grey" ]; +"320E" [ label="",shape="box",style="filled",color="grey" ]; +"322E" [ label="a7d2",shape="box",style="filled",color="grey" ]; +"332E" [ label="",shape="box",style="filled",color="grey" ]; +"340E" [ label="",shape="box",style="filled",color="grey" ]; +"344E" [ label="f55670",shape="box",style="filled",color="grey" ]; +"346E" [ label="1ed67841",shape="box",style="filled",color="grey" ]; +"348E" [ label="07283",shape="box",style="filled",color="grey" ]; +"374E" [ label="73ba1714ee",shape="box",style="filled",color="grey" ]; +"378E" [ label="27709106",shape="box",style="filled",color="grey" ]; +"452E" [ label="93ea0",shape="box",style="filled",color="grey" ]; +"508E" [ label="",shape="box",style="filled",color="grey" ]; +"524E" [ label="1d792d81",shape="box",style="filled",color="grey" ]; +"612E" [ label="a",shape="box",style="filled",color="grey" ]; +"626E" [ label="",shape="box",style="filled",color="grey" ]; +"638E" [ label="",shape="box",style="filled",color="grey" ]; +"644E" [ label="",shape="box",style="filled",color="grey" ]; +"654E" [ label="",shape="box",style="filled",color="grey" ]; +"672E" [ label="",shape="box",style="filled",color="grey" ]; +"302" [ label="23f94655294d3ff537f2915fa",shape="hexagon" ]; +"797E" [ label="",shape="box",style="filled",color="grey" ]; +"798E" [ label="a2eab7c9fa641e5f",shape="box",style="filled",color="grey" ]; +"303" [ label="a9058241db5b6b6c25569acdf5",shape="hexagon" ]; +"52E" [ label="b2babf3244213",shape="box",style="filled",color="grey" ]; +"650E" [ label="b354cd9e9dbb0bfa",shape="box",style="filled",color="grey" ]; +"304" [ label="bdbdb31bd777fb65dd6dd2d0e7",shape="hexagon" ]; +"50E" [ label="3bec1c012b498",shape="box",style="filled",color="grey" ]; +"640E" [ label="c54f0fc1e05",shape="box",style="filled",color="grey" ]; +"646E" [ label="9ab6c66dc",shape="box",style="filled",color="grey" ]; +"652E" [ label="699e3db878047",shape="box",style="filled",color="grey" ]; +"306" [ label="1d4ea80c7194689d69f9592186",shape="hexagon" ]; +"55E" [ label="8066f87a88f4e",shape="box",style="filled",color="grey" ]; +"220E" [ label="3a8173d6c",shape="box",style="filled",color="grey" ]; +"338E" [ label="24dfe1a997a",shape="box",style="filled",color="grey" ]; +"368E" [ label="65a1",shape="box",style="filled",color="grey" ]; +"486E" [ label="59a8b435ccd",shape="box",style="filled",color="grey" ]; +"490E" [ label="86e9b0428",shape="box",style="filled",color="grey" ]; +"562E" [ label="5a7a610a8a",shape="box",style="filled",color="grey" ]; +"564E" [ label="8f143077e",shape="box",style="filled",color="grey" ]; +"600E" [ label="6472c2861e0e0dd681",shape="box",style="filled",color="grey" ]; +"668E" [ label="f0f45e707",shape="box",style="filled",color="grey" ]; +"674E" [ label="95e93c4a13",shape="box",style="filled",color="grey" ]; +"698E" [ label="33e1de",shape="box",style="filled",color="grey" ]; +"307" [ label="7204950f6233bf9c9e1f00d4a870",shape="hexagon" ]; +"107E" [ label="ccceeef40edda78",shape="box",style="filled",color="grey" ]; +"308" [ label="a2c4b1d72e2da483a86ae0c62e5",shape="hexagon" ]; +"108E" [ label="eedc819a68add6",shape="box",style="filled",color="grey" ]; +"309" [ label="f603819d560c5603259aa05dca",shape="hexagon" ]; +"109E" [ label="acacfc83af504",shape="box",style="filled",color="grey" ]; +"310" [ label="2f43cba12702078b4e0d3bfdae2bc",shape="hexagon" ]; +"110E" [ label="3c1edc8de4795936",shape="box",style="filled",color="grey" ]; +"311" [ label="8f9cdc26798117dd3e9ee4a8770",shape="hexagon" ]; +"58E" [ label="881d373",shape="box",style="filled",color="grey" ]; +"234E" [ label="",shape="box",style="filled",color="grey" ]; +"300E" [ label="",shape="box",style="filled",color="grey" ]; +"306E" [ label="8c7cd9b93b1cbe48e1",shape="box",style="filled",color="grey" ]; +"314E" [ label="616d8a7b",shape="box",style="filled",color="grey" ]; +"342E" [ label="",shape="box",style="filled",color="grey" ]; +"354E" [ label="",shape="box",style="filled",color="grey" ]; +"370E" [ label="",shape="box",style="filled",color="grey" ]; +"382E" [ label="",shape="box",style="filled",color="grey" ]; +"422E" [ label="",shape="box",style="filled",color="grey" ]; +"444E" [ label="",shape="box",style="filled",color="grey" ]; +"582E" [ label="",shape="box",style="filled",color="grey" ]; +"620E" [ label="",shape="box",style="filled",color="grey" ]; +"630E" [ label="",shape="box",style="filled",color="grey" ]; +"684E" [ label="",shape="box",style="filled",color="grey" ]; +"696E" [ label="",shape="box",style="filled",color="grey" ]; +"801E" [ label="",shape="box",style="filled",color="grey" ]; +"312" [ label="97c9d726e27304311901a52ce",shape="hexagon",style="filled",color="#ff0000" ]; +"42E" [ label="1112164c2f7a",shape="box",style="filled",color="grey" ]; +"192E" [ label="5c609b12c",shape="box",style="filled",color="grey" ]; +"194E" [ label="00265",shape="box",style="filled",color="grey" ]; +"196E" [ label="04767",shape="box",style="filled",color="grey" ]; +"198E" [ label="f0d99f16",shape="box",style="filled",color="grey" ]; +"200E" [ label="",shape="box",style="filled",color="grey" ]; +"202E" [ label="6e186b",shape="box",style="filled",color="grey" ]; +"204E" [ label="d382",shape="box",style="filled",color="grey" ]; +"312E" [ label="c6b5321a",shape="box",style="filled",color="grey" ]; +"336E" [ label="",shape="box",style="filled",color="grey" ]; +"376E" [ label="",shape="box",style="filled",color="grey" ]; +"384E" [ label="aeb8",shape="box",style="filled",color="grey" ]; +"386E" [ label="2e53009d4a375",shape="box",style="filled",color="grey" ]; +"428E" [ label="",shape="box",style="filled",color="grey" ]; +"474E" [ label="",shape="box",style="filled",color="grey" ]; +"484E" [ label="",shape="box",style="filled",color="grey" ]; +"546E" [ label="dea1d1",shape="box",style="filled",color="grey" ]; +"548E" [ label="5a0b4b906a",shape="box",style="filled",color="grey" ]; +"314" [ label="1727041c622518c9dd24f7c211",shape="hexagon" ]; +"113E" [ label="49704867bee95",shape="box",style="filled",color="grey" ]; +"315" [ label="31f2f9aef958979f9f3532b9b",shape="hexagon",style="filled",color="#ff0000" ]; +"43E" [ label="47cd70f",shape="box",style="filled",color="grey" ]; +"240E" [ label="248df40dae",shape="box",style="filled",color="grey" ]; +"298E" [ label="",shape="box",style="filled",color="grey" ]; +"334E" [ label="9dd5bf47f",shape="box",style="filled",color="grey" ]; +"360E" [ label="",shape="box",style="filled",color="grey" ]; +"390E" [ label="28533c",shape="box",style="filled",color="grey" ]; +"418E" [ label="",shape="box",style="filled",color="grey" ]; +"492E" [ label="a4c7d0",shape="box",style="filled",color="grey" ]; +"502E" [ label="4f6f7f",shape="box",style="filled",color="grey" ]; +"584E" [ label="7ab64a969",shape="box",style="filled",color="grey" ]; +"588E" [ label="",shape="box",style="filled",color="grey" ]; +"602E" [ label="69",shape="box",style="filled",color="grey" ]; +"606E" [ label="67513d",shape="box",style="filled",color="grey" ]; +"662E" [ label="cf",shape="box",style="filled",color="grey" ]; +"316" [ label="a54092a3033f7d5e41e0a76c1",shape="hexagon" ]; +"51E" [ label="1467f017b74e",shape="box",style="filled",color="grey" ]; +"317" [ label="2043b477ac0393676a4309514d0",shape="hexagon" ]; +"116E" [ label="bdec8c86db51b9",shape="box",style="filled",color="grey" ]; +"318" [ label="ab48d1f65812bc0f8ab6941c3b5",shape="hexagon" ]; +"74E" [ label="81",shape="box",style="filled",color="grey" ]; +"319" [ label="ca3d67754cf62fdafbf0a1e0",shape="hexagon" ]; +"57E" [ label="75b14f1719d",shape="box",style="filled",color="grey" ]; +"94E" [ label="62f36ea98a",shape="box",style="filled",color="grey" ]; +"350E" [ label="e3a76d31ca59a",shape="box",style="filled",color="grey" ]; +"440E" [ label="b3cadc253f7",shape="box",style="filled",color="grey" ]; +"466E" [ label="fb58e11",shape="box",style="filled",color="grey" ]; +"676E" [ label="8606837526d81cdec",shape="box",style="filled",color="grey" ]; +"320" [ label="a7a7f3681dad1250b01cf80bc17",shape="hexagon" ]; +"60E" [ label="2c514b0cd8f7d3",shape="box",style="filled",color="grey" ]; +"366E" [ label="7e494b",shape="box",style="filled",color="grey" ]; +"434E" [ label="15d44ab97",shape="box",style="filled",color="grey" ]; +"458E" [ label="78b2d75d00166",shape="box",style="filled",color="grey" ]; +"618E" [ label="761e0f72f95",shape="box",style="filled",color="grey" ]; +"321" [ label="275afb2b215b966d9fac51b96b9",shape="hexagon" ]; +"72E" [ label="ac284d73563",shape="box",style="filled",color="grey" ]; +"362E" [ label="7e74e1587f3a4d208",shape="box",style="filled",color="grey" ]; +"372E" [ label="ffd1b1af3b6864078f3",shape="box",style="filled",color="grey" ]; +"572E" [ label="b38049e00",shape="box",style="filled",color="grey" ]; +"322" [ label="c3c93c700edc0cb4f95f03c04",shape="hexagon" ]; +"54E" [ label="99237fce1358",shape="box",style="filled",color="grey" ]; +"222E" [ label="3dcf8f454",shape="box",style="filled",color="grey" ]; +"302E" [ label="c5acd20cad2",shape="box",style="filled",color="grey" ]; +"556E" [ label="6c998bf2a5edd",shape="box",style="filled",color="grey" ]; +"558E" [ label="4b683",shape="box",style="filled",color="grey" ]; +"323" [ label="63a3d4fb9d38a0182be6e39e76",shape="hexagon" ]; +"37E" [ label="bba6e6e194ccf",shape="box",style="filled",color="grey" ]; +"208E" [ label="01938827",shape="box",style="filled",color="grey" ]; +"210E" [ label="9",shape="box",style="filled",color="grey" ]; +"352E" [ label="64ef1d545",shape="box",style="filled",color="grey" ]; +"450E" [ label="b473716",shape="box",style="filled",color="grey" ]; +"568E" [ label="7c13bf753da",shape="box",style="filled",color="grey" ]; +"576E" [ label="4e4a79111d",shape="box",style="filled",color="grey" ]; +"686E" [ label="af4abb0d6a99",shape="box",style="filled",color="grey" ]; +"324" [ label="4399cf78123dedd0dfe9776104",shape="hexagon" ]; +"228E" [ label="af9c489df53",shape="box",style="filled",color="grey" ]; +"248E" [ label="3703059dbc5a8",shape="box",style="filled",color="grey" ]; +"304E" [ label="8a46e6",shape="box",style="filled",color="grey" ]; +"468E" [ label="f9d09",shape="box",style="filled",color="grey" ]; +"578E" [ label="cd1e9af3dec2",shape="box",style="filled",color="grey" ]; +"660E" [ label="9e650e89bb",shape="box",style="filled",color="grey" ]; +"688E" [ label="f62b136b2171",shape="box",style="filled",color="grey" ]; +"694E" [ label="4727c415d06bcbef",shape="box",style="filled",color="grey" ]; +"714E" [ label="38b3b0d9",shape="box",style="filled",color="grey" ]; +"766E" [ label="a153512d982",shape="box",style="filled",color="grey" ]; +"325" [ label="40f253cd228f7ac2d0aee",shape="hexagon" ]; +"97E" [ label="a3ff993",shape="box",style="filled",color="grey" ]; +"506E" [ label="7528dd86b",shape="box",style="filled",color="grey" ]; +"326" [ label="89a2505da6179a80202d4a6c3",shape="hexagon" ]; +"61E" [ label="75eea05672a5",shape="box",style="filled",color="grey" ]; +"175E" [ label="3b0c08dd2ca",shape="box",style="filled",color="grey" ]; +"482E" [ label="a3781072b",shape="box",style="filled",color="grey" ]; +"328" [ label="2601085bde1b2450d64509f36",shape="hexagon" ]; +"75E" [ label="0efbd",shape="box",style="filled",color="grey" ]; +"580E" [ label="bb92d1da1f38d52f8ff",shape="box",style="filled",color="grey" ]; +"329" [ label="5c81103c751345d0ee0f4bd",shape="hexagon" ]; +"96E" [ label="b23526044",shape="box",style="filled",color="grey" ]; +"330" [ label="fcbd9ad14139718bc6fcc8b4",shape="hexagon" ]; +"100E" [ label="73ca543bf1",shape="box",style="filled",color="grey" ]; +"170E" [ label="c2f32e2cf9",shape="box",style="filled",color="grey" ]; +"333" [ label="44cbb41a9cfc15497eacd294",color="yellow",style="filled",shape="doubleoctagon" ]; +"63E" [ label="6a91",shape="box",style="filled",color="grey" ]; +"67E" [ label="b074e",shape="box",style="filled",color="grey" ]; +"68E" [ label="06209",shape="box",style="filled",color="grey" ]; +"69E" [ label="58e3dcc618",shape="box",style="filled",color="grey" ]; +"70E" [ label="eee44624da",shape="box",style="filled",color="grey" ]; +"71E" [ label="6a91",shape="box",style="filled",color="grey" ]; +"802E" [ label="e1e8c",shape="box",style="filled",color="grey" ]; +"793E" [ label="",shape="box",style="filled",color="grey" ]; +"334" [ label="b46b0756dba915943839e90a55",color="yellow",style="filled",shape="doubleoctagon" ]; +"64E" [ label="5fdf",shape="box",style="filled",color="grey" ]; +"81E" [ label="3eca1f94dc181",shape="box",style="filled",color="grey" ]; +"82E" [ label="6b1bb9b0e",shape="box",style="filled",color="grey" ]; +"83E" [ label="a54d477232",shape="box",style="filled",color="grey" ]; +"84E" [ label="a164d9f60fbbdd",shape="box",style="filled",color="grey" ]; +"85E" [ label="78c8463ea",shape="box",style="filled",color="grey" ]; +"86E" [ label="c110ba7",shape="box",style="filled",color="grey" ]; +"87E" [ label="3b63cdc0f",shape="box",style="filled",color="grey" ]; +"88E" [ label="6f578c5128",shape="box",style="filled",color="grey" ]; +"89E" [ label="3e048573fd",shape="box",style="filled",color="grey" ]; +"336" [ URL="tes hi",area="test",label="825c7994d5da13afe519861818",color="#ff0000",style="filled",shape="tripleoctagon" ]; +"1E" [ label="f4bef37b6a94bfd00",shape="box",style="filled",color="grey" ]; +"2E" [ label="d2647f8b6d8661d08",shape="box",style="filled",color="grey" ]; +"3E" [ label="964cb56d8f69ff058",shape="box",style="filled",color="grey" ]; +"4E" [ label="4f35e206816c3bd22",shape="box",style="filled",color="grey" ]; +"5E" [ label="affb2d716803a2d3e",shape="box",style="filled",color="grey" ]; +"6E" [ label="e4ae306d9bd669c70",shape="box",style="filled",color="grey" ]; +"7E" [ label="4dbf4395236fb03ed",shape="box",style="filled",color="grey" ]; +"8E" [ label="15b3ad672cd2f713a",shape="box",style="filled",color="grey" ]; +"9E" [ label="8d6e6e0cd9b842a47",shape="box",style="filled",color="grey" ]; +"10E" [ label="00d0dd018fe879f96",shape="box",style="filled",color="grey" ]; +"11E" [ label="f28b78d4803c",shape="box",style="filled",color="grey" ]; +"12E" [ label="2d886da042b5384b4",shape="box",style="filled",color="grey" ]; +"13E" [ label="548c0081a62132b44",shape="box",style="filled",color="grey" ]; +"14E" [ label="52126553e52385d16",shape="box",style="filled",color="grey" ]; +"15E" [ label="9fe716e738eaea34e",shape="box",style="filled",color="grey" ]; +"16E" [ label="5782807b5f575e0a8",shape="box",style="filled",color="grey" ]; +"17E" [ label="792fd6f9df1fa1e33",shape="box",style="filled",color="grey" ]; +"18E" [ label="c471b6fdbfb852661",shape="box",style="filled",color="grey" ]; +"19E" [ label="a84844dfd0052b3b5",shape="box",style="filled",color="grey" ]; +"20E" [ label="724dabdce9744d061",shape="box",style="filled",color="grey" ]; +"21E" [ label="57f7fd2eecec93c8b",shape="box",style="filled",color="grey" ]; +"22E" [ label="baba65f670ee34a88",shape="box",style="filled",color="grey" ]; +"23E" [ label="ac34ec0f0488b17ec",shape="box",style="filled",color="grey" ]; +"24E" [ label="51e74bec5513083bb",shape="box",style="filled",color="grey" ]; +"25E" [ label="8e2d970b2f820ee35",shape="box",style="filled",color="grey" ]; +"26E" [ label="19398d3cd6b9c674f",shape="box",style="filled",color="grey" ]; +"27E" [ label="6505e29f4a11d9530",shape="box",style="filled",color="grey" ]; +"28E" [ label="bc4824f07a9d2bba6",shape="box",style="filled",color="grey" ]; +"29E" [ label="3acbf8a1537e4e1a1",shape="box",style="filled",color="grey" ]; +"30E" [ label="536264e787cf70469",shape="box",style="filled",color="grey" ]; +"31E" [ label="d",shape="box",style="filled",color="grey" ]; +"65E" [ label="d4b2",shape="box",style="filled",color="grey" ]; +"119E" [ label="2a9caef7",shape="box",style="filled",color="grey" ]; +"150E" [ label="73d12",shape="box",style="filled",color="grey" ]; +"176E" [ label="8896166adc0",shape="box",style="filled",color="grey" ]; +"743E" [ label="9f",shape="box",style="filled",color="grey" ]; +"744E" [ label="2e1313c",shape="box",style="filled",color="grey" ]; +"764E" [ label="cd6",shape="box",style="filled",color="grey" ]; +"337" [ label="8304a439f91fc90b3fe8dd35be8",color="yellow",style="filled",shape="doubleoctagon" ]; +"120E" [ label="345d26b3f821fe",shape="box",style="filled",color="grey" ]; +"121E" [ label="357679fea1e2f",shape="box",style="filled",color="grey" ]; +"122E" [ label="c71043819b6a79",shape="box",style="filled",color="grey" ]; +"123E" [ label="f9df653b86fb8df",shape="box",style="filled",color="grey" ]; +"124E" [ label="020df871874cd",shape="box",style="filled",color="grey" ]; +"125E" [ label="4c52fdd8e396692",shape="box",style="filled",color="grey" ]; +"126E" [ label="8b98c3ddbe0b336",shape="box",style="filled",color="grey" ]; +"127E" [ label="d9f4abac731a9e",shape="box",style="filled",color="grey" ]; +"128E" [ label="50f4d9b97aefe",shape="box",style="filled",color="grey" ]; +"129E" [ label="ea920d9f5b295119",shape="box",style="filled",color="grey" ]; +"130E" [ label="ff5c9b242337c",shape="box",style="filled",color="grey" ]; +"131E" [ label="4e12f7ff0918",shape="box",style="filled",color="grey" ]; +"132E" [ label="ee3b6be71d59b",shape="box",style="filled",color="grey" ]; +"133E" [ label="615cd6b5e3d21c",shape="box",style="filled",color="grey" ]; +"134E" [ label="6d52dd1b198bb",shape="box",style="filled",color="grey" ]; +"135E" [ label="8c932e1e502dca",shape="box",style="filled",color="grey" ]; +"136E" [ label="e84330eef281284a",shape="box",style="filled",color="grey" ]; +"137E" [ label="85fc23f1c88b4",shape="box",style="filled",color="grey" ]; +"138E" [ label="5997cb0c083422",shape="box",style="filled",color="grey" ]; +"339" [ label="b1ffbabb24d71f67d1e0ce23c51",color="yellow",style="filled",shape="doubleoctagon" ]; +"151E" [ label="",shape="box",style="filled",color="grey" ]; +"153E" [ label="41a8b095c7fd3",shape="box",style="filled",color="grey" ]; +"154E" [ label="151bcc2a8de7ea634",shape="box",style="filled",color="grey" ]; +"155E" [ label="6c541cad8de1b15",shape="box",style="filled",color="grey" ]; +"156E" [ label="c935c7f4d1090ac",shape="box",style="filled",color="grey" ]; +"157E" [ label="5ce1fcfb042b",shape="box",style="filled",color="grey" ]; +"158E" [ label="531806429433",shape="box",style="filled",color="grey" ]; +"159E" [ label="d285240b89cb",shape="box",style="filled",color="grey" ]; +"160E" [ label="f22c27c0f0a54e",shape="box",style="filled",color="grey" ]; +"161E" [ label="8d0d8314d211d80",shape="box",style="filled",color="grey" ]; +"162E" [ label="",shape="box",style="filled",color="grey" ]; +"347" [ label="9652ab8b55fdb2a36d1f3fe020",shape="hexagon" ]; +"139E" [ label="ef8b68bb5772f3",shape="box",style="filled",color="grey" ]; +"795E" [ label="16c3ae29c0bc713",shape="box",style="filled",color="grey" ]; +"348" [ label="676bbe7d1c1fb71742df534ce8",shape="hexagon" ]; +"799E" [ label="a78eb40ae56aaa9",shape="box",style="filled",color="grey" ]; +"800E" [ label="6aae8d25951",shape="box",style="filled",color="grey" ]; +"349" [ label="66c0220688a999aaf7f1702d1",shape="hexagon" ]; +"141E" [ label="67b6a4dca3a6d",shape="box",style="filled",color="grey" ]; +"350" [ label="1322fb0818783e6f9a4f173d47c52",shape="hexagon" ]; +"142E" [ label="9696c0950295d8cb5",shape="box",style="filled",color="grey" ]; +"678E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; +"351" [ label="ff07977fca5513098d220d1eb3a",shape="hexagon" ]; +"143E" [ label="89a36b13f8c344b",shape="box",style="filled",color="grey" ]; +"232E" [ label="56292d076643",shape="box",style="filled",color="grey" ]; +"680E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; +"704E" [ label="431430c49",shape="box",style="filled",color="grey" ]; +"352" [ label="a97ef281eafc34b1630d450a1df",shape="hexagon" ]; +"144E" [ label="4ff4e275c710c3b",shape="box",style="filled",color="grey" ]; +"432E" [ label="d13da6273c9b4da",shape="box",style="filled",color="grey" ]; +"353" [ label="72cbb37db85ed3c6eda5dcf8",shape="hexagon" ]; +"145E" [ label="33ff9e43d5ab",shape="box",style="filled",color="grey" ]; +"354" [ label="0f6784e49852c0be0da23b16",shape="hexagon" ]; +"146E" [ label="d4f958b03a98",shape="box",style="filled",color="grey" ]; +"396E" [ label="8e24e9b4e",shape="box",style="filled",color="grey" ]; +"355" [ label="383f5c65cc6c25aa0a0e6dbb",shape="hexagon" ]; +"147E" [ label="1ff8ff951ee9",shape="box",style="filled",color="grey" ]; +"356" [ label="f52a45620969f0df4e6ae1dcd7",shape="hexagon" ]; +"148E" [ label="5256925081c812",shape="box",style="filled",color="grey" ]; +"357" [ label="1f5df34ad75a55a76ef4afa0a47",shape="hexagon" ]; +"149E" [ label="26a185dde9a93dd",shape="box",style="filled",color="grey" ]; +"358" [ label="45ba4d4c61c9601a26d59e47e0260",shape="hexagon" ]; +"167E" [ label="99bd3e7feeb710",shape="box",style="filled",color="grey" ]; +"359" [ label="f95344b0ae31693f3a2746597d4",shape="hexagon" ]; +"169E" [ label="4e8259973f1f",shape="box",style="filled",color="grey" ]; +"360" [ label="b79798b186d6b82288e8be4017d",shape="hexagon" ]; +"171E" [ label="63b079bd5847",shape="box",style="filled",color="grey" ]; +"361" [ label="47e0067f4d853afd2012f04daa8",shape="hexagon" ]; +"172E" [ label="92fb5d4a0805",shape="box",style="filled",color="grey" ]; +"362" [ label="f2b6201774de40a29b504b1f716",shape="hexagon" ]; +"173E" [ label="d7203571944b",shape="box",style="filled",color="grey" ]; +"363" [ label="800422ab81d804eef3e7b91dfba91",shape="hexagon" ]; +"174E" [ label="952316a1a5a785",shape="box",style="filled",color="grey" ]; +"364" [ label="35b941379e1af658078cffb83a2",shape="hexagon" ]; +"101E" [ label="331675c046693f",shape="box",style="filled",color="grey" ]; +"365" [ label="d4f7b7fba7afcf7a72397353ec",shape="hexagon" ]; +"102E" [ label="32c4684b55361",shape="box",style="filled",color="grey" ]; +"367" [ label="e4b45b7a2f884d3734bfd5985656",shape="hexagon" ]; +"104E" [ label="1333074979f2d0b",shape="box",style="filled",color="grey" ]; +"368" [ label="02c2ba83680ab57f236a33d702",shape="hexagon" ]; +"105E" [ label="084d4bfa5853e",shape="box",style="filled",color="grey" ]; +"369" [ label="9ccd974150a18260b207b6584caa",shape="hexagon" ]; +"106E" [ label="28f7bfc40c88e6a",shape="box",style="filled",color="grey" ]; +"374" [ label="653ae44d45dcadeb481b53027d",shape="hexagon" ]; +"111E" [ label="8f95518f48528",shape="box",style="filled",color="grey" ]; +"375" [ label="d66f542ef1ce4d02c59bec65e",shape="hexagon" ]; +"112E" [ label="2ef209509e2a",shape="box",style="filled",color="grey" ]; +"377" [ label="a2984b7a11e49440420058c1d80",shape="hexagon" ]; +"114E" [ label="ef42184297591d",shape="box",style="filled",color="grey" ]; +"378" [ label="31055116421c96b37f72a262bb",shape="hexagon" ]; +"115E" [ label="be9c5958196ed",shape="box",style="filled",color="grey" ]; +"380" [ label="8462bb2eec1a62d19a15865e57c92",shape="hexagon" ]; +"117E" [ label="16a795a1d63f30df",shape="box",style="filled",color="grey" ]; +"392E" [ label="85a34bc9616ff",shape="box",style="filled",color="grey" ]; +"381" [ label="c21eb96fe100a1efaa128181b7",shape="hexagon" ]; +"118E" [ label="f1b0d754353a6",shape="box",style="filled",color="grey" ]; +"382" [ label="e3e284d0cc803d98d674f9c3f6d",color="yellow",style="filled",shape="doubleoctagon" ]; +"177E" [ label="30417faf916",shape="box",style="filled",color="grey" ]; +"178E" [ label="e618df70814a",shape="box",style="filled",color="grey" ]; +"179E" [ label="fa90ddf10bd574",shape="box",style="filled",color="grey" ]; +"180E" [ label="815cc0b83d733",shape="box",style="filled",color="grey" ]; +"181E" [ label="f787d827958c",shape="box",style="filled",color="grey" ]; +"182E" [ label="f20f7f513e",shape="box",style="filled",color="grey" ]; +"183E" [ label="290907417e13",shape="box",style="filled",color="grey" ]; +"184E" [ label="e8386a8e1c8a",shape="box",style="filled",color="grey" ]; +"185E" [ label="319bc900218b",shape="box",style="filled",color="grey" ]; +"186E" [ label="3ba7afb0e48ae1",shape="box",style="filled",color="grey" ]; +"187E" [ label="6ba0776fc8e",shape="box",style="filled",color="grey" ]; +"188E" [ label="09847696ae",shape="box",style="filled",color="grey" ]; +"383" [ label="908f9ad506eae9ab6ada185e3",color="yellow",style="filled",shape="doubleoctagon" ]; +"730E" [ label="65694ca6d575",shape="box",style="filled",color="grey" ]; +"732E" [ label="37f57e81ebed95",shape="box",style="filled",color="grey" ]; +"741E" [ label="9b6c",shape="box",style="filled",color="grey" ]; +"765E" [ label="88ebe2e8782c",shape="box",style="filled",color="grey" ]; +"796E" [ label="901b2105a902ee7791",shape="box",style="filled",color="grey" ]; +"384" [ label="593caebf2037317648bb451aa79",color="yellow",style="filled",shape="doubleoctagon" ]; +"726E" [ label="351dd0aefe480c",shape="box",style="filled",color="grey" ]; +"728E" [ label="56e1a896",shape="box",style="filled",color="grey" ]; +"742E" [ label="5ba4693031",shape="box",style="filled",color="grey" ]; +"385" [ label="717c254aeffbb527dabfc",shape="hexagon" ]; +"328E" [ label="123cc6d1ac",shape="box",style="filled",color="grey" ]; +"496E" [ label="",shape="box",style="filled",color="grey" ]; +"594E" [ label="7f8c557bcf3889",shape="box",style="filled",color="grey" ]; +"622E" [ label="da3d5",shape="box",style="filled",color="grey" ]; +"754E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; +"755E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; +"756E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"757E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; +"758E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; +"759E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"760E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; +"761E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; +"762E" [ label="1e2298c4bb",shape="box",style="filled",color="grey" ]; +"1" -> "189E" [ label=" ",color="blue",arrowhead="dot" ]; +"1" -> "790E" [ label=" ",color="blue",arrowhead="dot" ]; +"2" -> "191E" [ label=" ",color="blue",arrowhead="dot" ]; +"3" -> "193E" [ label=" ",color="blue",arrowhead="dot" ]; +"4" -> "195E" [ label=" ",color="blue",arrowhead="dot" ]; +"5" -> "197E" [ label=" ",color="blue",arrowhead="dot" ]; +"6" -> "199E" [ label=" ",color="blue",arrowhead="dot" ]; +"7" -> "201E" [ label=" ",color="blue",arrowhead="dot" ]; +"8" -> "203E" [ label=" ",color="blue",arrowhead="dot" ]; +"9" -> "725E" [ label=" ",color="blue",arrowhead="dot" ]; +"9" -> "785E" [ label=" ",color="blue",arrowhead="dot" ]; +"10" -> "205E" [ label=" ",color="blue",arrowhead="dot" ]; +"11" -> "207E" [ label=" ",color="blue",arrowhead="dot" ]; +"12" -> "209E" [ label=" ",color="blue",arrowhead="dot" ]; +"13" -> "211E" [ label=" ",color="blue",arrowhead="dot" ]; +"14" -> "213E" [ label=" ",color="blue",arrowhead="dot" ]; +"15" -> "215E" [ label=" ",color="blue",arrowhead="dot" ]; +"16" -> "727E" [ label=" ",color="blue",arrowhead="dot" ]; +"16" -> "784E" [ label=" ",color="blue",arrowhead="dot" ]; +"17" -> "217E" [ label=" ",color="blue",arrowhead="dot" ]; +"17" -> "787E" [ label=" ",color="blue",arrowhead="dot" ]; +"18" -> "219E" [ label=" ",color="blue",arrowhead="dot" ]; +"19" -> "221E" [ label=" ",color="blue",arrowhead="dot" ]; +"20" -> "223E" [ label=" ",color="blue",arrowhead="dot" ]; +"21" -> "225E" [ label=" ",color="blue",arrowhead="dot" ]; +"22" -> "227E" [ label=" ",color="blue",arrowhead="dot" ]; +"22" -> "792E" [ label=" ",color="blue",arrowhead="dot" ]; +"23" -> "231E" [ label=" ",color="blue",arrowhead="dot" ]; +"24" -> "233E" [ label=" ",color="blue",arrowhead="dot" ]; +"25" -> "235E" [ label=" ",color="blue",arrowhead="dot" ]; +"26" -> "237E" [ label=" ",color="blue",arrowhead="dot" ]; +"27" -> "239E" [ label=" ",color="blue",arrowhead="dot" ]; +"27" -> "783E" [ label=" ",color="blue",arrowhead="dot" ]; +"28" -> "241E" [ label=" ",color="blue",arrowhead="dot" ]; +"28" -> "791E" [ label=" ",color="blue",arrowhead="dot" ]; +"29" -> "243E" [ label=" ",color="blue",arrowhead="dot" ]; +"30" -> "245E" [ label=" ",color="blue",arrowhead="dot" ]; +"31" -> "247E" [ label=" ",color="blue",arrowhead="dot" ]; +"32" -> "249E" [ label=" ",color="blue",arrowhead="dot" ]; +"33" -> "251E" [ label=" ",color="blue",arrowhead="dot" ]; +"34" -> "253E" [ label=" ",color="blue",arrowhead="dot" ]; +"35" -> "255E" [ label=" ",color="blue",arrowhead="dot" ]; +"36" -> "257E" [ label=" ",color="blue",arrowhead="dot" ]; +"37" -> "259E" [ label=" ",color="blue",arrowhead="dot" ]; +"38" -> "261E" [ label=" ",color="blue",arrowhead="dot" ]; +"39" -> "263E" [ label=" ",color="blue",arrowhead="dot" ]; +"40" -> "265E" [ label=" ",color="blue",arrowhead="dot" ]; +"41" -> "267E" [ label=" ",color="blue",arrowhead="dot" ]; +"42" -> "269E" [ label=" ",color="blue",arrowhead="dot" ]; +"43" -> "271E" [ label=" ",color="blue",arrowhead="dot" ]; +"44" -> "273E" [ label=" ",color="blue",arrowhead="dot" ]; +"45" -> "275E" [ label=" ",color="blue",arrowhead="dot" ]; +"46" -> "277E" [ label=" ",color="blue",arrowhead="dot" ]; +"47" -> "279E" [ label=" ",color="blue",arrowhead="dot" ]; +"48" -> "281E" [ label=" ",color="blue",arrowhead="dot" ]; +"49" -> "283E" [ label=" ",color="blue",arrowhead="dot" ]; +"50" -> "285E" [ label=" ",color="blue",arrowhead="dot" ]; +"51" -> "287E" [ label=" ",color="blue",arrowhead="dot" ]; +"52" -> "289E" [ label=" ",color="blue",arrowhead="dot" ]; +"53" -> "291E" [ label=" ",color="blue",arrowhead="dot" ]; +"54" -> "293E" [ label=" ",color="blue",arrowhead="dot" ]; +"55" -> "745E" [ label=" ",color="blue",arrowhead="dot" ]; +"56" -> "295E" [ label=" ",color="blue",arrowhead="dot" ]; +"57" -> "297E" [ label=" ",color="blue",arrowhead="dot" ]; +"58" -> "299E" [ label=" ",color="blue",arrowhead="dot" ]; +"59" -> "301E" [ label=" ",color="blue",arrowhead="dot" ]; +"59" -> "789E" [ label=" ",color="blue",arrowhead="dot" ]; +"60" -> "303E" [ label=" ",color="blue",arrowhead="dot" ]; +"61" -> "305E" [ label=" ",color="blue",arrowhead="dot" ]; +"62" -> "307E" [ label=" ",color="blue",arrowhead="dot" ]; +"63" -> "309E" [ label=" ",color="blue",arrowhead="dot" ]; +"64" -> "311E" [ label=" ",color="blue",arrowhead="dot" ]; +"65" -> "313E" [ label=" ",color="blue",arrowhead="dot" ]; +"66" -> "315E" [ label=" ",color="blue",arrowhead="dot" ]; +"67" -> "317E" [ label=" ",color="blue",arrowhead="dot" ]; +"68" -> "319E" [ label=" ",color="blue",arrowhead="dot" ]; +"69" -> "746E" [ label=" ",color="blue",arrowhead="dot" ]; +"70" -> "321E" [ label=" ",color="blue",arrowhead="dot" ]; +"71" -> "327E" [ label=" ",color="blue",arrowhead="dot" ]; +"72" -> "329E" [ label=" ",color="blue",arrowhead="dot" ]; +"73" -> "331E" [ label=" ",color="blue",arrowhead="dot" ]; +"74" -> "333E" [ label=" ",color="blue",arrowhead="dot" ]; +"75" -> "335E" [ label=" ",color="blue",arrowhead="dot" ]; +"76" -> "337E" [ label=" ",color="blue",arrowhead="dot" ]; +"77" -> "339E" [ label=" ",color="blue",arrowhead="dot" ]; +"78" -> "341E" [ label=" ",color="blue",arrowhead="dot" ]; +"79" -> "343E" [ label=" ",color="blue",arrowhead="dot" ]; +"80" -> "345E" [ label=" ",color="blue",arrowhead="dot" ]; +"81" -> "347E" [ label=" ",color="blue",arrowhead="dot" ]; +"82" -> "349E" [ label=" ",color="blue",arrowhead="dot" ]; +"83" -> "351E" [ label=" ",color="blue",arrowhead="dot" ]; +"84" -> "353E" [ label=" ",color="blue",arrowhead="dot" ]; +"85" -> "355E" [ label=" ",color="blue",arrowhead="dot" ]; +"85" -> "788E" [ label=" ",color="blue",arrowhead="dot" ]; +"86" -> "357E" [ label=" ",color="blue",arrowhead="dot" ]; +"87" -> "359E" [ label=" ",color="blue",arrowhead="dot" ]; +"88" -> "361E" [ label=" ",color="blue",arrowhead="dot" ]; +"89" -> "363E" [ label=" ",color="blue",arrowhead="dot" ]; +"90" -> "365E" [ label=" ",color="blue",arrowhead="dot" ]; +"91" -> "367E" [ label=" ",color="blue",arrowhead="dot" ]; +"92" -> "369E" [ label=" ",color="blue",arrowhead="dot" ]; +"93" -> "729E" [ label=" ",color="blue",arrowhead="dot" ]; +"94" -> "371E" [ label=" ",color="blue",arrowhead="dot" ]; +"95" -> "373E" [ label=" ",color="blue",arrowhead="dot" ]; +"96" -> "375E" [ label=" ",color="blue",arrowhead="dot" ]; +"97" -> "747E" [ label=" ",color="blue",arrowhead="dot" ]; +"98" -> "377E" [ label=" ",color="blue",arrowhead="dot" ]; +"99" -> "379E" [ label=" ",color="blue",arrowhead="dot" ]; +"100" -> "381E" [ label=" ",color="blue",arrowhead="dot" ]; +"101" -> "383E" [ label=" ",color="blue",arrowhead="dot" ]; +"102" -> "385E" [ label=" ",color="blue",arrowhead="dot" ]; +"103" -> "387E" [ label=" ",color="blue",arrowhead="dot" ]; +"104" -> "389E" [ label=" ",color="blue",arrowhead="dot" ]; +"105" -> "391E" [ label=" ",color="blue",arrowhead="dot" ]; +"106" -> "393E" [ label=" ",color="blue",arrowhead="dot" ]; +"107" -> "395E" [ label=" ",color="blue",arrowhead="dot" ]; +"108" -> "397E" [ label=" ",color="blue",arrowhead="dot" ]; +"109" -> "399E" [ label=" ",color="blue",arrowhead="dot" ]; +"110" -> "401E" [ label=" ",color="blue",arrowhead="dot" ]; +"111" -> "403E" [ label=" ",color="blue",arrowhead="dot" ]; +"112" -> "405E" [ label=" ",color="blue",arrowhead="dot" ]; +"113" -> "407E" [ label=" ",color="blue",arrowhead="dot" ]; +"114" -> "409E" [ label=" ",color="blue",arrowhead="dot" ]; +"115" -> "411E" [ label=" ",color="blue",arrowhead="dot" ]; +"116" -> "413E" [ label=" ",color="blue",arrowhead="dot" ]; +"117" -> "415E" [ label=" ",color="blue",arrowhead="dot" ]; +"118" -> "417E" [ label=" ",color="blue",arrowhead="dot" ]; +"119" -> "419E" [ label=" ",color="blue",arrowhead="dot" ]; +"120" -> "421E" [ label=" ",color="blue",arrowhead="dot" ]; +"121" -> "423E" [ label=" ",color="blue",arrowhead="dot" ]; +"122" -> "748E" [ label=" ",color="blue",arrowhead="dot" ]; +"123" -> "425E" [ label=" ",color="blue",arrowhead="dot" ]; +"124" -> "427E" [ label=" ",color="blue",arrowhead="dot" ]; +"124" -> "786E" [ label=" ",color="blue",arrowhead="dot" ]; +"125" -> "431E" [ label=" ",color="blue",arrowhead="dot" ]; +"126" -> "433E" [ label=" ",color="blue",arrowhead="dot" ]; +"127" -> "435E" [ label=" ",color="blue",arrowhead="dot" ]; +"128" -> "437E" [ label=" ",color="blue",arrowhead="dot" ]; +"129" -> "439E" [ label=" ",color="blue",arrowhead="dot" ]; +"130" -> "441E" [ label=" ",color="blue",arrowhead="dot" ]; +"131" -> "443E" [ label=" ",color="blue",arrowhead="dot" ]; +"132" -> "445E" [ label=" ",color="blue",arrowhead="dot" ]; +"133" -> "749E" [ label=" ",color="blue",arrowhead="dot" ]; +"134" -> "447E" [ label=" ",color="blue",arrowhead="dot" ]; +"135" -> "449E" [ label=" ",color="blue",arrowhead="dot" ]; +"135" -> "769E" [ label=" ",color="blue",arrowhead="dot" ]; +"135" -> "770E" [ label=" ",color="blue",arrowhead="dot" ]; +"136" -> "451E" [ label=" ",color="blue",arrowhead="dot" ]; +"137" -> "453E" [ label=" ",color="blue",arrowhead="dot" ]; +"138" -> "455E" [ label=" ",color="blue",arrowhead="dot" ]; +"139" -> "457E" [ label=" ",color="blue",arrowhead="dot" ]; +"140" -> "459E" [ label=" ",color="blue",arrowhead="dot" ]; +"141" -> "461E" [ label=" ",color="blue",arrowhead="dot" ]; +"142" -> "463E" [ label=" ",color="blue",arrowhead="dot" ]; +"143" -> "465E" [ label=" ",color="blue",arrowhead="dot" ]; +"144" -> "467E" [ label=" ",color="blue",arrowhead="dot" ]; +"145" -> "469E" [ label=" ",color="blue",arrowhead="dot" ]; +"146" -> "471E" [ label=" ",color="blue",arrowhead="dot" ]; +"147" -> "473E" [ label=" ",color="blue",arrowhead="dot" ]; +"148" -> "475E" [ label=" ",color="blue",arrowhead="dot" ]; +"149" -> "477E" [ label=" ",color="blue",arrowhead="dot" ]; +"150" -> "479E" [ label=" ",color="blue",arrowhead="dot" ]; +"151" -> "481E" [ label=" ",color="blue",arrowhead="dot" ]; +"152" -> "483E" [ label=" ",color="blue",arrowhead="dot" ]; +"153" -> "731E" [ label=" ",color="blue",arrowhead="dot" ]; +"154" -> "750E" [ label=" ",color="blue",arrowhead="dot" ]; +"155" -> "485E" [ label=" ",color="blue",arrowhead="dot" ]; +"156" -> "487E" [ label=" ",color="blue",arrowhead="dot" ]; +"157" -> "489E" [ label=" ",color="blue",arrowhead="dot" ]; +"158" -> "491E" [ label=" ",color="blue",arrowhead="dot" ]; +"159" -> "495E" [ label=" ",color="blue",arrowhead="dot" ]; +"160" -> "499E" [ label=" ",color="blue",arrowhead="dot" ]; +"161" -> "501E" [ label=" ",color="blue",arrowhead="dot" ]; +"162" -> "503E" [ label=" ",color="blue",arrowhead="dot" ]; +"163" -> "505E" [ label=" ",color="blue",arrowhead="dot" ]; +"164" -> "507E" [ label=" ",color="blue",arrowhead="dot" ]; +"165" -> "509E" [ label=" ",color="blue",arrowhead="dot" ]; +"166" -> "511E" [ label=" ",color="blue",arrowhead="dot" ]; +"167" -> "513E" [ label=" ",color="blue",arrowhead="dot" ]; +"168" -> "515E" [ label=" ",color="blue",arrowhead="dot" ]; +"169" -> "517E" [ label=" ",color="blue",arrowhead="dot" ]; +"170" -> "519E" [ label=" ",color="blue",arrowhead="dot" ]; +"171" -> "521E" [ label=" ",color="blue",arrowhead="dot" ]; +"172" -> "523E" [ label=" ",color="blue",arrowhead="dot" ]; +"173" -> "525E" [ label=" ",color="blue",arrowhead="dot" ]; +"174" -> "527E" [ label=" ",color="blue",arrowhead="dot" ]; +"175" -> "529E" [ label=" ",color="blue",arrowhead="dot" ]; +"176" -> "531E" [ label=" ",color="blue",arrowhead="dot" ]; +"177" -> "533E" [ label=" ",color="blue",arrowhead="dot" ]; +"178" -> "535E" [ label=" ",color="blue",arrowhead="dot" ]; +"179" -> "537E" [ label=" ",color="blue",arrowhead="dot" ]; +"180" -> "539E" [ label=" ",color="blue",arrowhead="dot" ]; +"181" -> "541E" [ label=" ",color="blue",arrowhead="dot" ]; +"182" -> "543E" [ label=" ",color="blue",arrowhead="dot" ]; +"183" -> "545E" [ label=" ",color="blue",arrowhead="dot" ]; +"184" -> "547E" [ label=" ",color="blue",arrowhead="dot" ]; +"185" -> "549E" [ label=" ",color="blue",arrowhead="dot" ]; +"186" -> "551E" [ label=" ",color="blue",arrowhead="dot" ]; +"187" -> "553E" [ label=" ",color="blue",arrowhead="dot" ]; +"188" -> "555E" [ label=" ",color="blue",arrowhead="dot" ]; +"189" -> "557E" [ label=" ",color="blue",arrowhead="dot" ]; +"190" -> "559E" [ label=" ",color="blue",arrowhead="dot" ]; +"191" -> "561E" [ label=" ",color="blue",arrowhead="dot" ]; +"192" -> "563E" [ label=" ",color="blue",arrowhead="dot" ]; +"193" -> "565E" [ label=" ",color="blue",arrowhead="dot" ]; +"194" -> "567E" [ label=" ",color="blue",arrowhead="dot" ]; +"195" -> "569E" [ label=" ",color="blue",arrowhead="dot" ]; +"196" -> "571E" [ label=" ",color="blue",arrowhead="dot" ]; +"197" -> "573E" [ label=" ",color="blue",arrowhead="dot" ]; +"198" -> "575E" [ label=" ",color="blue",arrowhead="dot" ]; +"199" -> "577E" [ label=" ",color="blue",arrowhead="dot" ]; +"200" -> "579E" [ label=" ",color="blue",arrowhead="dot" ]; +"201" -> "581E" [ label=" ",color="blue",arrowhead="dot" ]; +"202" -> "583E" [ label=" ",color="blue",arrowhead="dot" ]; +"203" -> "585E" [ label=" ",color="blue",arrowhead="dot" ]; +"204" -> "587E" [ label=" ",color="blue",arrowhead="dot" ]; +"205" -> "751E" [ label=" ",color="blue",arrowhead="dot" ]; +"206" -> "589E" [ label=" ",color="blue",arrowhead="dot" ]; +"207" -> "593E" [ label=" ",color="blue",arrowhead="dot" ]; +"208" -> "597E" [ label=" ",color="blue",arrowhead="dot" ]; +"209" -> "599E" [ label=" ",color="blue",arrowhead="dot" ]; +"210" -> "601E" [ label=" ",color="blue",arrowhead="dot" ]; +"211" -> "603E" [ label=" ",color="blue",arrowhead="dot" ]; +"212" -> "605E" [ label=" ",color="blue",arrowhead="dot" ]; +"213" -> "607E" [ label=" ",color="blue",arrowhead="dot" ]; +"214" -> "609E" [ label=" ",color="blue",arrowhead="dot" ]; +"215" -> "611E" [ label=" ",color="blue",arrowhead="dot" ]; +"216" -> "613E" [ label=" ",color="blue",arrowhead="dot" ]; +"217" -> "615E" [ label=" ",color="blue",arrowhead="dot" ]; +"218" -> "617E" [ label=" ",color="blue",arrowhead="dot" ]; +"219" -> "619E" [ label=" ",color="blue",arrowhead="dot" ]; +"220" -> "621E" [ label=" ",color="blue",arrowhead="dot" ]; +"221" -> "623E" [ label=" ",color="blue",arrowhead="dot" ]; +"222" -> "752E" [ label=" ",color="blue",arrowhead="dot" ]; +"223" -> "625E" [ label=" ",color="blue",arrowhead="dot" ]; +"224" -> "627E" [ label=" ",color="blue",arrowhead="dot" ]; +"225" -> "629E" [ label=" ",color="blue",arrowhead="dot" ]; +"226" -> "631E" [ label=" ",color="blue",arrowhead="dot" ]; +"227" -> "633E" [ label=" ",color="blue",arrowhead="dot" ]; +"228" -> "635E" [ label=" ",color="blue",arrowhead="dot" ]; +"229" -> "637E" [ label=" ",color="blue",arrowhead="dot" ]; +"230" -> "639E" [ label=" ",color="blue",arrowhead="dot" ]; +"231" -> "641E" [ label=" ",color="blue",arrowhead="dot" ]; +"232" -> "643E" [ label=" ",color="blue",arrowhead="dot" ]; +"233" -> "645E" [ label=" ",color="blue",arrowhead="dot" ]; +"234" -> "647E" [ label=" ",color="blue",arrowhead="dot" ]; +"235" -> "649E" [ label=" ",color="blue",arrowhead="dot" ]; +"236" -> "651E" [ label=" ",color="blue",arrowhead="dot" ]; +"237" -> "653E" [ label=" ",color="blue",arrowhead="dot" ]; +"238" -> "655E" [ label=" ",color="blue",arrowhead="dot" ]; +"239" -> "657E" [ label=" ",color="blue",arrowhead="dot" ]; +"240" -> "659E" [ label=" ",color="blue",arrowhead="dot" ]; +"241" -> "661E" [ label=" ",color="blue",arrowhead="dot" ]; +"242" -> "663E" [ label=" ",color="blue",arrowhead="dot" ]; +"243" -> "665E" [ label=" ",color="blue",arrowhead="dot" ]; +"244" -> "667E" [ label=" ",color="blue",arrowhead="dot" ]; +"245" -> "669E" [ label=" ",color="blue",arrowhead="dot" ]; +"246" -> "671E" [ label=" ",color="blue",arrowhead="dot" ]; +"247" -> "673E" [ label=" ",color="blue",arrowhead="dot" ]; +"248" -> "675E" [ label=" ",color="blue",arrowhead="dot" ]; +"249" -> "679E" [ label=" ",color="blue",arrowhead="dot" ]; +"250" -> "753E" [ label=" ",color="blue",arrowhead="dot" ]; +"251" -> "681E" [ label=" ",color="blue",arrowhead="dot" ]; +"252" -> "683E" [ label=" ",color="blue",arrowhead="dot" ]; +"253" -> "685E" [ label=" ",color="blue",arrowhead="dot" ]; +"254" -> "687E" [ label=" ",color="blue",arrowhead="dot" ]; +"255" -> "689E" [ label=" ",color="blue",arrowhead="dot" ]; +"256" -> "691E" [ label=" ",color="blue",arrowhead="dot" ]; +"257" -> "693E" [ label=" ",color="blue",arrowhead="dot" ]; +"258" -> "695E" [ label=" ",color="blue",arrowhead="dot" ]; +"259" -> "697E" [ label=" ",color="blue",arrowhead="dot" ]; +"260" -> "699E" [ label=" ",color="blue",arrowhead="dot" ]; +"261" -> "703E" [ label=" ",color="blue",arrowhead="dot" ]; +"262" -> "705E" [ label=" ",color="blue",arrowhead="dot" ]; +"264" -> "709E" [ label=" ",color="blue",arrowhead="dot" ]; +"265" -> "711E" [ label=" ",color="blue",arrowhead="dot" ]; +"266" -> "713E" [ label=" ",color="blue",arrowhead="dot" ]; +"267" -> "715E" [ label=" ",color="blue",arrowhead="dot" ]; +"268" -> "717E" [ label=" ",color="blue",arrowhead="dot" ]; +"269" -> "719E" [ label=" ",color="blue",arrowhead="dot" ]; +"270" -> "721E" [ label=" ",color="blue",arrowhead="dot" ]; +"272" -> "34E" [ label=" ",color="blue",arrowhead="dot" ]; +"272" -> "252E" [ label=" ",color="blue",arrowhead="dot" ]; +"272" -> "436E" [ label=" ",color="blue",arrowhead="dot" ]; +"274" -> "59E" [ label=" ",color="blue",arrowhead="dot" ]; +"274" -> "500E" [ label=" ",color="blue",arrowhead="dot" ]; +"274" -> "720E" [ label=" ",color="blue",arrowhead="dot" ]; +"275" -> "98E" [ label=" ",color="blue",arrowhead="dot" ]; +"278" -> "35E" [ label=" ",color="blue",arrowhead="dot" ]; +"278" -> "488E" [ label=" ",color="blue",arrowhead="dot" ]; +"278" -> "598E" [ label=" ",color="blue",arrowhead="dot" ]; +"278" -> "604E" [ label=" ",color="blue",arrowhead="dot" ]; +"278" -> "628E" [ label=" ",color="blue",arrowhead="dot" ]; +"279" -> "99E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "242E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "270E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "272E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "284E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "286E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "288E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "586E" [ label=" ",color="blue",arrowhead="dot" ]; +"280" -> "763E" [ label=" ",color="blue",arrowhead="dot" ]; +"281" -> "45E" [ label=" ",color="blue",arrowhead="dot" ]; +"281" -> "470E" [ label=" ",color="blue",arrowhead="dot" ]; +"281" -> "670E" [ label=" ",color="blue",arrowhead="dot" ]; +"281" -> "722E" [ label=" ",color="blue",arrowhead="dot" ]; +"282" -> "103E" [ label=" ",color="blue",arrowhead="dot" ]; +"283" -> "165E" [ label=" ",color="blue",arrowhead="dot" ]; +"284" -> "39E" [ label=" ",color="blue",arrowhead="dot" ]; +"284" -> "224E" [ label=" ",color="blue",arrowhead="dot" ]; +"284" -> "268E" [ label=" ",color="blue",arrowhead="dot" ]; +"284" -> "632E" [ label=" ",color="blue",arrowhead="dot" ]; +"284" -> "710E" [ label=" ",color="blue",arrowhead="dot" ]; +"285" -> "53E" [ label=" ",color="blue",arrowhead="dot" ]; +"286" -> "38E" [ label=" ",color="blue",arrowhead="dot" ]; +"286" -> "166E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "40E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "218E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "244E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "246E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "258E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "290E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "292E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "308E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "318E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "388E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "472E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "478E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "566E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "570E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "574E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "608E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "614E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "658E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "664E" [ label=" ",color="blue",arrowhead="dot" ]; +"288" -> "682E" [ label=" ",color="blue",arrowhead="dot" ]; +"289" -> "41E" [ label=" ",color="blue",arrowhead="dot" ]; +"289" -> "636E" [ label=" ",color="blue",arrowhead="dot" ]; +"289" -> "642E" [ label=" ",color="blue",arrowhead="dot" ]; +"289" -> "690E" [ label=" ",color="blue",arrowhead="dot" ]; +"289" -> "700E" [ label=" ",color="blue",arrowhead="dot" ]; +"290" -> "56E" [ label=" ",color="blue",arrowhead="dot" ]; +"290" -> "264E" [ label=" ",color="blue",arrowhead="dot" ]; +"290" -> "510E" [ label=" ",color="blue",arrowhead="dot" ]; +"290" -> "718E" [ label=" ",color="blue",arrowhead="dot" ]; +"291" -> "66E" [ label=" ",color="blue",arrowhead="dot" ]; +"291" -> "76E" [ label=" ",color="blue",arrowhead="dot" ]; +"291" -> "610E" [ label=" ",color="blue",arrowhead="dot" ]; +"292" -> "73E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "49E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "214E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "216E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "236E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "278E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "358E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "398E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "400E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "402E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "404E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "406E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "408E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "412E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "438E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "448E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "476E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "504E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "552E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "634E" [ label=" ",color="blue",arrowhead="dot" ]; +"293" -> "768E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "44E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "92E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "250E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "316E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "380E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "424E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "442E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "446E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "454E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "460E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "462E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "648E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "656E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "666E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "692E" [ label=" ",color="blue",arrowhead="dot" ]; +"295" -> "712E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "47E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "330E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "514E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "516E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "518E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "520E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "522E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "526E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "528E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "530E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "532E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "534E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "536E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "538E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "540E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "542E" [ label=" ",color="blue",arrowhead="dot" ]; +"296" -> "544E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "46E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "93E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "206E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "426E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "550E" [ label=" ",color="blue",arrowhead="dot" ]; +"297" -> "706E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "36E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "95E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "364E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "394E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "420E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "456E" [ label=" ",color="blue",arrowhead="dot" ]; +"298" -> "624E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "48E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "168E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "260E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "282E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "554E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "590E" [ label=" ",color="blue",arrowhead="dot" ]; +"299" -> "767E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "62E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "190E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "226E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "238E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "254E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "256E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "262E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "266E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "274E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "276E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "294E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "296E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "310E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "320E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "322E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "332E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "340E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "344E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "346E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "348E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "374E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "378E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "452E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "508E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "524E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "612E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "626E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "638E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "644E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "654E" [ label=" ",color="blue",arrowhead="dot" ]; +"300" -> "672E" [ label=" ",color="blue",arrowhead="dot" ]; +"302" -> "797E" [ label=" ",color="blue",arrowhead="dot" ]; +"302" -> "798E" [ label=" ",color="blue",arrowhead="dot" ]; +"303" -> "52E" [ label=" ",color="blue",arrowhead="dot" ]; +"303" -> "650E" [ label=" ",color="blue",arrowhead="dot" ]; +"304" -> "50E" [ label=" ",color="blue",arrowhead="dot" ]; +"304" -> "640E" [ label=" ",color="blue",arrowhead="dot" ]; +"304" -> "646E" [ label=" ",color="blue",arrowhead="dot" ]; +"304" -> "652E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "55E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "220E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "338E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "368E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "486E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "490E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "562E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "564E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "600E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "668E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "674E" [ label=" ",color="blue",arrowhead="dot" ]; +"306" -> "698E" [ label=" ",color="blue",arrowhead="dot" ]; +"307" -> "107E" [ label=" ",color="blue",arrowhead="dot" ]; +"308" -> "108E" [ label=" ",color="blue",arrowhead="dot" ]; +"309" -> "109E" [ label=" ",color="blue",arrowhead="dot" ]; +"310" -> "110E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "58E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "234E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "300E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "306E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "314E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "342E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "354E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "370E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "382E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "422E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "444E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "582E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "620E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "630E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "684E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "696E" [ label=" ",color="blue",arrowhead="dot" ]; +"311" -> "801E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "42E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "192E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "194E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "196E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "198E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "200E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "202E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "204E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "312E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "336E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "376E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "384E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "386E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "428E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "474E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "484E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "546E" [ label=" ",color="blue",arrowhead="dot" ]; +"312" -> "548E" [ label=" ",color="blue",arrowhead="dot" ]; +"314" -> "113E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "43E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "240E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "298E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "334E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "360E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "390E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "418E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "492E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "502E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "584E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "588E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "602E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "606E" [ label=" ",color="blue",arrowhead="dot" ]; +"315" -> "662E" [ label=" ",color="blue",arrowhead="dot" ]; +"316" -> "51E" [ label=" ",color="blue",arrowhead="dot" ]; +"317" -> "116E" [ label=" ",color="blue",arrowhead="dot" ]; +"318" -> "74E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "57E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "94E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "350E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "440E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "466E" [ label=" ",color="blue",arrowhead="dot" ]; +"319" -> "676E" [ label=" ",color="blue",arrowhead="dot" ]; +"320" -> "60E" [ label=" ",color="blue",arrowhead="dot" ]; +"320" -> "366E" [ label=" ",color="blue",arrowhead="dot" ]; +"320" -> "434E" [ label=" ",color="blue",arrowhead="dot" ]; +"320" -> "458E" [ label=" ",color="blue",arrowhead="dot" ]; +"320" -> "618E" [ label=" ",color="blue",arrowhead="dot" ]; +"321" -> "72E" [ label=" ",color="blue",arrowhead="dot" ]; +"321" -> "362E" [ label=" ",color="blue",arrowhead="dot" ]; +"321" -> "372E" [ label=" ",color="blue",arrowhead="dot" ]; +"321" -> "572E" [ label=" ",color="blue",arrowhead="dot" ]; +"322" -> "54E" [ label=" ",color="blue",arrowhead="dot" ]; +"322" -> "222E" [ label=" ",color="blue",arrowhead="dot" ]; +"322" -> "302E" [ label=" ",color="blue",arrowhead="dot" ]; +"322" -> "556E" [ label=" ",color="blue",arrowhead="dot" ]; +"322" -> "558E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "37E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "208E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "210E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "352E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "450E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "568E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "576E" [ label=" ",color="blue",arrowhead="dot" ]; +"323" -> "686E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "228E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "248E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "304E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "468E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "578E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "660E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "688E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "694E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "714E" [ label=" ",color="blue",arrowhead="dot" ]; +"324" -> "766E" [ label=" ",color="blue",arrowhead="dot" ]; +"325" -> "97E" [ label=" ",color="blue",arrowhead="dot" ]; +"325" -> "506E" [ label=" ",color="blue",arrowhead="dot" ]; +"326" -> "61E" [ label=" ",color="blue",arrowhead="dot" ]; +"326" -> "175E" [ label=" ",color="blue",arrowhead="dot" ]; +"326" -> "482E" [ label=" ",color="blue",arrowhead="dot" ]; +"328" -> "75E" [ label=" ",color="blue",arrowhead="dot" ]; +"328" -> "580E" [ label=" ",color="blue",arrowhead="dot" ]; +"329" -> "96E" [ label=" ",color="blue",arrowhead="dot" ]; +"330" -> "100E" [ label=" ",color="blue",arrowhead="dot" ]; +"330" -> "170E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "63E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "67E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "68E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "69E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "70E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "71E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "802E" [ label=" ",color="blue",arrowhead="dot" ]; +"333" -> "793E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "64E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "81E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "82E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "83E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "84E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "85E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "86E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "87E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "88E" [ label=" ",color="blue",arrowhead="dot" ]; +"334" -> "89E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "1E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "2E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "3E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "4E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "5E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "6E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "7E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "8E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "9E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "10E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "11E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "12E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "13E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "14E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "15E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "16E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "17E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "18E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "19E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "20E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "21E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "22E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "23E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "24E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "25E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "26E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "27E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "28E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "29E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "30E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "31E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "65E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "119E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "150E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "176E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "743E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "744E" [ label=" ",color="blue",arrowhead="dot" ]; +"336" -> "764E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "120E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "121E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "122E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "123E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "124E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "125E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "126E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "127E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "128E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "129E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "130E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "131E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "132E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "133E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "134E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "135E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "136E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "137E" [ label=" ",color="blue",arrowhead="dot" ]; +"337" -> "138E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "151E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "153E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "154E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "155E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "156E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "157E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "158E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "159E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "160E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "161E" [ label=" ",color="blue",arrowhead="dot" ]; +"339" -> "162E" [ label=" ",color="blue",arrowhead="dot" ]; +"347" -> "139E" [ label=" ",color="blue",arrowhead="dot" ]; +"347" -> "795E" [ label=" ",color="blue",arrowhead="dot" ]; +"348" -> "799E" [ label=" ",color="blue",arrowhead="dot" ]; +"348" -> "800E" [ label=" ",color="blue",arrowhead="dot" ]; +"349" -> "141E" [ label=" ",color="blue",arrowhead="dot" ]; +"350" -> "142E" [ label=" ",color="blue",arrowhead="dot" ]; +"350" -> "678E" [ label=" ",color="blue",arrowhead="dot" ]; +"351" -> "143E" [ label=" ",color="blue",arrowhead="dot" ]; +"351" -> "232E" [ label=" ",color="blue",arrowhead="dot" ]; +"351" -> "680E" [ label=" ",color="blue",arrowhead="dot" ]; +"351" -> "704E" [ label=" ",color="blue",arrowhead="dot" ]; +"352" -> "144E" [ label=" ",color="blue",arrowhead="dot" ]; +"352" -> "432E" [ label=" ",color="blue",arrowhead="dot" ]; +"353" -> "145E" [ label=" ",color="blue",arrowhead="dot" ]; +"354" -> "146E" [ label=" ",color="blue",arrowhead="dot" ]; +"354" -> "396E" [ label=" ",color="blue",arrowhead="dot" ]; +"355" -> "147E" [ label=" ",color="blue",arrowhead="dot" ]; +"356" -> "148E" [ label=" ",color="blue",arrowhead="dot" ]; +"357" -> "149E" [ label=" ",color="blue",arrowhead="dot" ]; +"358" -> "167E" [ label=" ",color="blue",arrowhead="dot" ]; +"359" -> "169E" [ label=" ",color="blue",arrowhead="dot" ]; +"360" -> "171E" [ label=" ",color="blue",arrowhead="dot" ]; +"361" -> "172E" [ label=" ",color="blue",arrowhead="dot" ]; +"362" -> "173E" [ label=" ",color="blue",arrowhead="dot" ]; +"363" -> "174E" [ label=" ",color="blue",arrowhead="dot" ]; +"364" -> "101E" [ label=" ",color="blue",arrowhead="dot" ]; +"365" -> "102E" [ label=" ",color="blue",arrowhead="dot" ]; +"367" -> "104E" [ label=" ",color="blue",arrowhead="dot" ]; +"368" -> "105E" [ label=" ",color="blue",arrowhead="dot" ]; +"369" -> "106E" [ label=" ",color="blue",arrowhead="dot" ]; +"374" -> "111E" [ label=" ",color="blue",arrowhead="dot" ]; +"375" -> "112E" [ label=" ",color="blue",arrowhead="dot" ]; +"377" -> "114E" [ label=" ",color="blue",arrowhead="dot" ]; +"378" -> "115E" [ label=" ",color="blue",arrowhead="dot" ]; +"380" -> "117E" [ label=" ",color="blue",arrowhead="dot" ]; +"380" -> "392E" [ label=" ",color="blue",arrowhead="dot" ]; +"381" -> "118E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "177E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "178E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "179E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "180E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "181E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "182E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "183E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "184E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "185E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "186E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "187E" [ label=" ",color="blue",arrowhead="dot" ]; +"382" -> "188E" [ label=" ",color="blue",arrowhead="dot" ]; +"383" -> "730E" [ label=" ",color="blue",arrowhead="dot" ]; +"383" -> "732E" [ label=" ",color="blue",arrowhead="dot" ]; +"383" -> "741E" [ label=" ",color="blue",arrowhead="dot" ]; +"383" -> "765E" [ label=" ",color="blue",arrowhead="dot" ]; +"383" -> "796E" [ label=" ",color="blue",arrowhead="dot" ]; +"384" -> "726E" [ label=" ",color="blue",arrowhead="dot" ]; +"384" -> "728E" [ label=" ",color="blue",arrowhead="dot" ]; +"384" -> "742E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "328E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "496E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "594E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "622E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "754E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "755E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "756E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "757E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "758E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "759E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "760E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "761E" [ label=" ",color="blue",arrowhead="dot" ]; +"385" -> "762E" [ label=" ",color="blue",arrowhead="dot" ]; +"1E" -> "34E" [ color="purple",arrowhead="none" ]; +"2E" -> "35E" [ color="purple",arrowhead="none" ]; +"3E" -> "36E" [ color="purple",arrowhead="none" ]; +"4E" -> "37E" [ color="purple",arrowhead="none" ]; +"5E" -> "38E" [ color="purple",arrowhead="none" ]; +"6E" -> "39E" [ color="purple",arrowhead="none" ]; +"7E" -> "40E" [ color="purple",arrowhead="none" ]; +"9E" -> "41E" [ color="purple",arrowhead="none" ]; +"10E" -> "42E" [ color="purple",arrowhead="none" ]; +"11E" -> "43E" [ color="purple",arrowhead="none" ]; +"12E" -> "44E" [ color="purple",arrowhead="none" ]; +"13E" -> "45E" [ color="purple",arrowhead="none" ]; +"14E" -> "46E" [ color="purple",arrowhead="none" ]; +"15E" -> "47E" [ color="purple",arrowhead="none" ]; +"16E" -> "48E" [ color="purple",arrowhead="none" ]; +"49E" -> "17E" [ color="purple",arrowhead="none" ]; +"18E" -> "50E" [ color="purple",arrowhead="none" ]; +"19E" -> "51E" [ color="purple",arrowhead="none" ]; +"20E" -> "52E" [ color="purple",arrowhead="none" ]; +"21E" -> "53E" [ color="purple",arrowhead="none" ]; +"22E" -> "54E" [ color="purple",arrowhead="none" ]; +"23E" -> "55E" [ color="purple",arrowhead="none" ]; +"24E" -> "56E" [ color="purple",arrowhead="none" ]; +"25E" -> "57E" [ color="purple",arrowhead="none" ]; +"26E" -> "58E" [ color="purple",arrowhead="none" ]; +"27E" -> "59E" [ color="purple",arrowhead="none" ]; +"28E" -> "60E" [ color="purple",arrowhead="none" ]; +"29E" -> "61E" [ color="purple",arrowhead="none" ]; +"30E" -> "62E" [ color="purple",arrowhead="none" ]; +"31E" -> "63E" [ color="purple",arrowhead="none" ]; +"64E" -> "65E" [ color="purple",arrowhead="none" ]; +"66E" -> "8E" [ color="purple",arrowhead="none" ]; +"71E" -> "76E" [ color="purple",arrowhead="none" ]; +"67E" -> "72E" [ color="purple",arrowhead="none" ]; +"68E" -> "73E" [ color="purple",arrowhead="none" ]; +"69E" -> "74E" [ color="purple",arrowhead="none" ]; +"70E" -> "75E" [ color="purple",arrowhead="none" ]; +"81E" -> "92E" [ color="purple",arrowhead="none" ]; +"82E" -> "93E" [ color="purple",arrowhead="none" ]; +"83E" -> "94E" [ color="purple",arrowhead="none" ]; +"84E" -> "95E" [ color="purple",arrowhead="none" ]; +"85E" -> "96E" [ color="purple",arrowhead="none" ]; +"86E" -> "97E" [ color="purple",arrowhead="none" ]; +"87E" -> "98E" [ color="purple",arrowhead="none" ]; +"88E" -> "99E" [ color="purple",arrowhead="none" ]; +"89E" -> "100E" [ color="purple",arrowhead="none" ]; +"101E" -> "120E" [ color="purple",arrowhead="none" ]; +"102E" -> "121E" [ color="purple",arrowhead="none" ]; +"103E" -> "122E" [ color="purple",arrowhead="none" ]; +"104E" -> "123E" [ color="purple",arrowhead="none" ]; +"105E" -> "124E" [ color="purple",arrowhead="none" ]; +"106E" -> "125E" [ color="purple",arrowhead="none" ]; +"107E" -> "126E" [ color="purple",arrowhead="none" ]; +"108E" -> "127E" [ color="purple",arrowhead="none" ]; +"109E" -> "128E" [ color="purple",arrowhead="none" ]; +"110E" -> "129E" [ color="purple",arrowhead="none" ]; +"111E" -> "130E" [ color="purple",arrowhead="none" ]; +"112E" -> "131E" [ color="purple",arrowhead="none" ]; +"113E" -> "132E" [ color="purple",arrowhead="none" ]; +"114E" -> "133E" [ color="purple",arrowhead="none" ]; +"115E" -> "134E" [ color="purple",arrowhead="none" ]; +"116E" -> "135E" [ color="purple",arrowhead="none" ]; +"117E" -> "136E" [ color="purple",arrowhead="none" ]; +"118E" -> "137E" [ color="purple",arrowhead="none" ]; +"119E" -> "138E" [ color="purple",arrowhead="none" ]; +"139E" -> "151E" [ color="purple",arrowhead="none" ]; +"141E" -> "153E" [ color="purple",arrowhead="none" ]; +"142E" -> "154E" [ color="purple",arrowhead="none" ]; +"143E" -> "155E" [ color="purple",arrowhead="none" ]; +"144E" -> "156E" [ color="purple",arrowhead="none" ]; +"145E" -> "157E" [ color="purple",arrowhead="none" ]; +"146E" -> "158E" [ color="purple",arrowhead="none" ]; +"147E" -> "159E" [ color="purple",arrowhead="none" ]; +"148E" -> "160E" [ color="purple",arrowhead="none" ]; +"149E" -> "161E" [ color="purple",arrowhead="none" ]; +"150E" -> "162E" [ color="purple",arrowhead="none" ]; +"165E" -> "177E" [ color="purple",arrowhead="none" ]; +"166E" -> "178E" [ color="purple",arrowhead="none" ]; +"167E" -> "179E" [ color="purple",arrowhead="none" ]; +"168E" -> "180E" [ color="purple",arrowhead="none" ]; +"169E" -> "181E" [ color="purple",arrowhead="none" ]; +"170E" -> "182E" [ color="purple",arrowhead="none" ]; +"171E" -> "183E" [ color="purple",arrowhead="none" ]; +"172E" -> "184E" [ color="purple",arrowhead="none" ]; +"173E" -> "185E" [ color="purple",arrowhead="none" ]; +"174E" -> "186E" [ color="purple",arrowhead="none" ]; +"175E" -> "187E" [ color="purple",arrowhead="none" ]; +"176E" -> "188E" [ color="purple",arrowhead="none" ]; +"189E" -> "190E" [ color="purple",arrowhead="none" ]; +"191E" -> "192E" [ color="purple",arrowhead="none" ]; +"193E" -> "194E" [ color="purple",arrowhead="none" ]; +"195E" -> "196E" [ color="purple",arrowhead="none" ]; +"197E" -> "198E" [ color="purple",arrowhead="none" ]; +"199E" -> "200E" [ color="purple",arrowhead="none" ]; +"201E" -> "202E" [ color="purple",arrowhead="none" ]; +"203E" -> "204E" [ color="purple",arrowhead="none" ]; +"205E" -> "206E" [ color="purple",arrowhead="none" ]; +"207E" -> "208E" [ color="purple",arrowhead="none" ]; +"209E" -> "210E" [ color="purple",arrowhead="none" ]; +"412E" -> "211E" [ color="purple",arrowhead="none" ]; +"214E" -> "213E" [ color="purple",arrowhead="none" ]; +"216E" -> "215E" [ color="purple",arrowhead="none" ]; +"217E" -> "218E" [ color="purple",arrowhead="none" ]; +"219E" -> "220E" [ color="purple",arrowhead="none" ]; +"221E" -> "222E" [ color="purple",arrowhead="none" ]; +"223E" -> "224E" [ color="purple",arrowhead="none" ]; +"225E" -> "226E" [ color="purple",arrowhead="none" ]; +"227E" -> "228E" [ color="purple",arrowhead="none" ]; +"231E" -> "232E" [ color="purple",arrowhead="none" ]; +"233E" -> "234E" [ color="purple",arrowhead="none" ]; +"236E" -> "235E" [ color="purple",arrowhead="none" ]; +"237E" -> "238E" [ color="purple",arrowhead="none" ]; +"239E" -> "240E" [ color="purple",arrowhead="none" ]; +"241E" -> "242E" [ color="purple",arrowhead="none" ]; +"243E" -> "244E" [ color="purple",arrowhead="none" ]; +"245E" -> "246E" [ color="purple",arrowhead="none" ]; +"247E" -> "248E" [ color="purple",arrowhead="none" ]; +"249E" -> "250E" [ color="purple",arrowhead="none" ]; +"251E" -> "252E" [ color="purple",arrowhead="none" ]; +"253E" -> "254E" [ color="purple",arrowhead="none" ]; +"255E" -> "256E" [ color="purple",arrowhead="none" ]; +"257E" -> "258E" [ color="purple",arrowhead="none" ]; +"259E" -> "260E" [ color="purple",arrowhead="none" ]; +"261E" -> "262E" [ color="purple",arrowhead="none" ]; +"263E" -> "264E" [ color="purple",arrowhead="none" ]; +"265E" -> "266E" [ color="purple",arrowhead="none" ]; +"267E" -> "268E" [ color="purple",arrowhead="none" ]; +"269E" -> "270E" [ color="purple",arrowhead="none" ]; +"271E" -> "272E" [ color="purple",arrowhead="none" ]; +"273E" -> "274E" [ color="purple",arrowhead="none" ]; +"275E" -> "276E" [ color="purple",arrowhead="none" ]; +"278E" -> "277E" [ color="purple",arrowhead="none" ]; +"279E" -> "767E" [ color="purple",arrowhead="none" ]; +"281E" -> "282E" [ color="purple",arrowhead="none" ]; +"283E" -> "284E" [ color="purple",arrowhead="none" ]; +"285E" -> "286E" [ color="purple",arrowhead="none" ]; +"768E" -> "287E" [ color="purple",arrowhead="none" ]; +"289E" -> "290E" [ color="purple",arrowhead="none" ]; +"291E" -> "292E" [ color="purple",arrowhead="none" ]; +"293E" -> "294E" [ color="purple",arrowhead="none" ]; +"295E" -> "296E" [ color="purple",arrowhead="none" ]; +"297E" -> "298E" [ color="purple",arrowhead="none" ]; +"299E" -> "300E" [ color="purple",arrowhead="none" ]; +"301E" -> "302E" [ color="purple",arrowhead="none" ]; +"303E" -> "304E" [ color="purple",arrowhead="none" ]; +"305E" -> "306E" [ color="purple",arrowhead="none" ]; +"307E" -> "308E" [ color="purple",arrowhead="none" ]; +"309E" -> "310E" [ color="purple",arrowhead="none" ]; +"311E" -> "312E" [ color="purple",arrowhead="none" ]; +"313E" -> "314E" [ color="purple",arrowhead="none" ]; +"315E" -> "316E" [ color="purple",arrowhead="none" ]; +"317E" -> "318E" [ color="purple",arrowhead="none" ]; +"319E" -> "320E" [ color="purple",arrowhead="none" ]; +"321E" -> "322E" [ color="purple",arrowhead="none" ]; +"327E" -> "800E" [ color="purple",arrowhead="none" ]; +"329E" -> "330E" [ color="purple",arrowhead="none" ]; +"331E" -> "332E" [ color="purple",arrowhead="none" ]; +"333E" -> "334E" [ color="purple",arrowhead="none" ]; +"335E" -> "336E" [ color="purple",arrowhead="none" ]; +"337E" -> "338E" [ color="purple",arrowhead="none" ]; +"339E" -> "340E" [ color="purple",arrowhead="none" ]; +"341E" -> "342E" [ color="purple",arrowhead="none" ]; +"343E" -> "344E" [ color="purple",arrowhead="none" ]; +"345E" -> "346E" [ color="purple",arrowhead="none" ]; +"347E" -> "348E" [ color="purple",arrowhead="none" ]; +"349E" -> "350E" [ color="purple",arrowhead="none" ]; +"351E" -> "352E" [ color="purple",arrowhead="none" ]; +"353E" -> "354E" [ color="purple",arrowhead="none" ]; +"412E" -> "355E" [ color="purple",arrowhead="none" ]; +"357E" -> "358E" [ color="purple",arrowhead="none" ]; +"359E" -> "360E" [ color="purple",arrowhead="none" ]; +"361E" -> "362E" [ color="purple",arrowhead="none" ]; +"363E" -> "364E" [ color="purple",arrowhead="none" ]; +"365E" -> "366E" [ color="purple",arrowhead="none" ]; +"367E" -> "368E" [ color="purple",arrowhead="none" ]; +"369E" -> "370E" [ color="purple",arrowhead="none" ]; +"371E" -> "372E" [ color="purple",arrowhead="none" ]; +"373E" -> "374E" [ color="purple",arrowhead="none" ]; +"375E" -> "376E" [ color="purple",arrowhead="none" ]; +"377E" -> "378E" [ color="purple",arrowhead="none" ]; +"379E" -> "380E" [ color="purple",arrowhead="none" ]; +"381E" -> "382E" [ color="purple",arrowhead="none" ]; +"383E" -> "384E" [ color="purple",arrowhead="none" ]; +"385E" -> "386E" [ color="purple",arrowhead="none" ]; +"387E" -> "388E" [ color="purple",arrowhead="none" ]; +"389E" -> "390E" [ color="purple",arrowhead="none" ]; +"391E" -> "392E" [ color="purple",arrowhead="none" ]; +"393E" -> "394E" [ color="purple",arrowhead="none" ]; +"395E" -> "396E" [ color="purple",arrowhead="none" ]; +"397E" -> "398E" [ color="purple",arrowhead="none" ]; +"399E" -> "400E" [ color="purple",arrowhead="none" ]; +"402E" -> "401E" [ color="purple",arrowhead="none" ]; +"404E" -> "403E" [ color="purple",arrowhead="none" ]; +"406E" -> "405E" [ color="purple",arrowhead="none" ]; +"408E" -> "407E" [ color="purple",arrowhead="none" ]; +"236E" -> "409E" [ color="purple",arrowhead="none" ]; +"412E" -> "411E" [ color="purple",arrowhead="none" ]; +"412E" -> "413E" [ color="purple",arrowhead="none" ]; +"278E" -> "415E" [ color="purple",arrowhead="none" ]; +"417E" -> "418E" [ color="purple",arrowhead="none" ]; +"419E" -> "420E" [ color="purple",arrowhead="none" ]; +"421E" -> "422E" [ color="purple",arrowhead="none" ]; +"423E" -> "424E" [ color="purple",arrowhead="none" ]; +"425E" -> "426E" [ color="purple",arrowhead="none" ]; +"427E" -> "428E" [ color="purple",arrowhead="none" ]; +"431E" -> "432E" [ color="purple",arrowhead="none" ]; +"433E" -> "434E" [ color="purple",arrowhead="none" ]; +"435E" -> "436E" [ color="purple",arrowhead="none" ]; +"438E" -> "437E" [ color="purple",arrowhead="none" ]; +"439E" -> "440E" [ color="purple",arrowhead="none" ]; +"441E" -> "442E" [ color="purple",arrowhead="none" ]; +"443E" -> "444E" [ color="purple",arrowhead="none" ]; +"445E" -> "446E" [ color="purple",arrowhead="none" ]; +"448E" -> "447E" [ color="purple",arrowhead="none" ]; +"449E" -> "450E" [ color="purple",arrowhead="none" ]; +"451E" -> "452E" [ color="purple",arrowhead="none" ]; +"453E" -> "454E" [ color="purple",arrowhead="none" ]; +"455E" -> "456E" [ color="purple",arrowhead="none" ]; +"457E" -> "458E" [ color="purple",arrowhead="none" ]; +"459E" -> "460E" [ color="purple",arrowhead="none" ]; +"461E" -> "462E" [ color="purple",arrowhead="none" ]; +"236E" -> "463E" [ color="purple",arrowhead="none" ]; +"465E" -> "466E" [ color="purple",arrowhead="none" ]; +"467E" -> "468E" [ color="purple",arrowhead="none" ]; +"469E" -> "470E" [ color="purple",arrowhead="none" ]; +"471E" -> "472E" [ color="purple",arrowhead="none" ]; +"473E" -> "474E" [ color="purple",arrowhead="none" ]; +"476E" -> "475E" [ color="purple",arrowhead="none" ]; +"477E" -> "478E" [ color="purple",arrowhead="none" ]; +"479E" -> "358E" [ color="purple",arrowhead="none" ]; +"481E" -> "482E" [ color="purple",arrowhead="none" ]; +"483E" -> "484E" [ color="purple",arrowhead="none" ]; +"485E" -> "486E" [ color="purple",arrowhead="none" ]; +"487E" -> "488E" [ color="purple",arrowhead="none" ]; +"489E" -> "490E" [ color="purple",arrowhead="none" ]; +"491E" -> "492E" [ color="purple",arrowhead="none" ]; +"495E" -> "795E" [ color="purple",arrowhead="none" ]; +"499E" -> "500E" [ color="purple",arrowhead="none" ]; +"501E" -> "502E" [ color="purple",arrowhead="none" ]; +"504E" -> "503E" [ color="purple",arrowhead="none" ]; +"505E" -> "506E" [ color="purple",arrowhead="none" ]; +"507E" -> "508E" [ color="purple",arrowhead="none" ]; +"509E" -> "510E" [ color="purple",arrowhead="none" ]; +"412E" -> "511E" [ color="purple",arrowhead="none" ]; +"513E" -> "514E" [ color="purple",arrowhead="none" ]; +"515E" -> "516E" [ color="purple",arrowhead="none" ]; +"517E" -> "518E" [ color="purple",arrowhead="none" ]; +"519E" -> "520E" [ color="purple",arrowhead="none" ]; +"521E" -> "522E" [ color="purple",arrowhead="none" ]; +"523E" -> "524E" [ color="purple",arrowhead="none" ]; +"525E" -> "526E" [ color="purple",arrowhead="none" ]; +"527E" -> "528E" [ color="purple",arrowhead="none" ]; +"529E" -> "530E" [ color="purple",arrowhead="none" ]; +"531E" -> "532E" [ color="purple",arrowhead="none" ]; +"533E" -> "534E" [ color="purple",arrowhead="none" ]; +"535E" -> "536E" [ color="purple",arrowhead="none" ]; +"537E" -> "538E" [ color="purple",arrowhead="none" ]; +"539E" -> "540E" [ color="purple",arrowhead="none" ]; +"541E" -> "542E" [ color="purple",arrowhead="none" ]; +"543E" -> "544E" [ color="purple",arrowhead="none" ]; +"545E" -> "546E" [ color="purple",arrowhead="none" ]; +"547E" -> "548E" [ color="purple",arrowhead="none" ]; +"549E" -> "550E" [ color="purple",arrowhead="none" ]; +"551E" -> "552E" [ color="purple",arrowhead="none" ]; +"553E" -> "554E" [ color="purple",arrowhead="none" ]; +"555E" -> "556E" [ color="purple",arrowhead="none" ]; +"557E" -> "558E" [ color="purple",arrowhead="none" ]; +"278E" -> "559E" [ color="purple",arrowhead="none" ]; +"561E" -> "562E" [ color="purple",arrowhead="none" ]; +"563E" -> "564E" [ color="purple",arrowhead="none" ]; +"565E" -> "566E" [ color="purple",arrowhead="none" ]; +"567E" -> "568E" [ color="purple",arrowhead="none" ]; +"569E" -> "570E" [ color="purple",arrowhead="none" ]; +"571E" -> "572E" [ color="purple",arrowhead="none" ]; +"573E" -> "574E" [ color="purple",arrowhead="none" ]; +"575E" -> "576E" [ color="purple",arrowhead="none" ]; +"577E" -> "578E" [ color="purple",arrowhead="none" ]; +"579E" -> "580E" [ color="purple",arrowhead="none" ]; +"581E" -> "582E" [ color="purple",arrowhead="none" ]; +"583E" -> "584E" [ color="purple",arrowhead="none" ]; +"585E" -> "586E" [ color="purple",arrowhead="none" ]; +"587E" -> "588E" [ color="purple",arrowhead="none" ]; +"589E" -> "590E" [ color="purple",arrowhead="none" ]; +"593E" -> "594E" [ color="purple",arrowhead="none" ]; +"597E" -> "598E" [ color="purple",arrowhead="none" ]; +"599E" -> "600E" [ color="purple",arrowhead="none" ]; +"601E" -> "602E" [ color="purple",arrowhead="none" ]; +"603E" -> "604E" [ color="purple",arrowhead="none" ]; +"605E" -> "606E" [ color="purple",arrowhead="none" ]; +"607E" -> "608E" [ color="purple",arrowhead="none" ]; +"609E" -> "610E" [ color="purple",arrowhead="none" ]; +"611E" -> "612E" [ color="purple",arrowhead="none" ]; +"613E" -> "614E" [ color="purple",arrowhead="none" ]; +"615E" -> "358E" [ color="purple",arrowhead="none" ]; +"617E" -> "618E" [ color="purple",arrowhead="none" ]; +"619E" -> "620E" [ color="purple",arrowhead="none" ]; +"621E" -> "622E" [ color="purple",arrowhead="none" ]; +"623E" -> "624E" [ color="purple",arrowhead="none" ]; +"625E" -> "626E" [ color="purple",arrowhead="none" ]; +"627E" -> "628E" [ color="purple",arrowhead="none" ]; +"629E" -> "630E" [ color="purple",arrowhead="none" ]; +"631E" -> "632E" [ color="purple",arrowhead="none" ]; +"634E" -> "633E" [ color="purple",arrowhead="none" ]; +"635E" -> "636E" [ color="purple",arrowhead="none" ]; +"637E" -> "638E" [ color="purple",arrowhead="none" ]; +"639E" -> "640E" [ color="purple",arrowhead="none" ]; +"641E" -> "642E" [ color="purple",arrowhead="none" ]; +"643E" -> "644E" [ color="purple",arrowhead="none" ]; +"645E" -> "646E" [ color="purple",arrowhead="none" ]; +"647E" -> "648E" [ color="purple",arrowhead="none" ]; +"649E" -> "650E" [ color="purple",arrowhead="none" ]; +"651E" -> "652E" [ color="purple",arrowhead="none" ]; +"653E" -> "654E" [ color="purple",arrowhead="none" ]; +"655E" -> "656E" [ color="purple",arrowhead="none" ]; +"657E" -> "658E" [ color="purple",arrowhead="none" ]; +"659E" -> "660E" [ color="purple",arrowhead="none" ]; +"661E" -> "662E" [ color="purple",arrowhead="none" ]; +"663E" -> "664E" [ color="purple",arrowhead="none" ]; +"665E" -> "666E" [ color="purple",arrowhead="none" ]; +"667E" -> "668E" [ color="purple",arrowhead="none" ]; +"669E" -> "670E" [ color="purple",arrowhead="none" ]; +"671E" -> "672E" [ color="purple",arrowhead="none" ]; +"673E" -> "674E" [ color="purple",arrowhead="none" ]; +"675E" -> "676E" [ color="purple",arrowhead="none" ]; +"679E" -> "680E" [ color="purple",arrowhead="none" ]; +"681E" -> "682E" [ color="purple",arrowhead="none" ]; +"683E" -> "684E" [ color="purple",arrowhead="none" ]; +"685E" -> "686E" [ color="purple",arrowhead="none" ]; +"687E" -> "688E" [ color="purple",arrowhead="none" ]; +"689E" -> "690E" [ color="purple",arrowhead="none" ]; +"691E" -> "692E" [ color="purple",arrowhead="none" ]; +"693E" -> "694E" [ color="purple",arrowhead="none" ]; +"695E" -> "696E" [ color="purple",arrowhead="none" ]; +"697E" -> "698E" [ color="purple",arrowhead="none" ]; +"699E" -> "700E" [ color="purple",arrowhead="none" ]; +"703E" -> "704E" [ color="purple",arrowhead="none" ]; +"705E" -> "706E" [ color="purple",arrowhead="none" ]; +"709E" -> "710E" [ color="purple",arrowhead="none" ]; +"711E" -> "712E" [ color="purple",arrowhead="none" ]; +"713E" -> "714E" [ color="purple",arrowhead="none" ]; +"715E" -> "398E" [ color="purple",arrowhead="none" ]; +"717E" -> "718E" [ color="purple",arrowhead="none" ]; +"719E" -> "720E" [ color="purple",arrowhead="none" ]; +"721E" -> "722E" [ color="purple",arrowhead="none" ]; +"725E" -> "726E" [ color="purple",arrowhead="none" ]; +"727E" -> "728E" [ color="purple",arrowhead="none" ]; +"729E" -> "730E" [ color="purple",arrowhead="none" ]; +"731E" -> "732E" [ color="purple",arrowhead="none" ]; +"741E" -> "743E" [ color="purple",arrowhead="none" ]; +"742E" -> "744E" [ color="purple",arrowhead="none" ]; +"745E" -> "754E" [ color="purple",arrowhead="none" ]; +"746E" -> "755E" [ color="purple",arrowhead="none" ]; +"747E" -> "756E" [ color="purple",arrowhead="none" ]; +"748E" -> "757E" [ color="purple",arrowhead="none" ]; +"749E" -> "758E" [ color="purple",arrowhead="none" ]; +"750E" -> "759E" [ color="purple",arrowhead="none" ]; +"751E" -> "760E" [ color="purple",arrowhead="none" ]; +"752E" -> "761E" [ color="purple",arrowhead="none" ]; +"753E" -> "762E" [ color="purple",arrowhead="none" ]; +"763E" -> "764E" [ color="purple",arrowhead="none" ]; +"765E" -> "766E" [ color="purple",arrowhead="none" ]; +"770E" -> "783E" [ color="purple",arrowhead="none" ]; +"770E" -> "784E" [ color="purple",arrowhead="none" ]; +"769E" -> "785E" [ color="purple",arrowhead="none" ]; +"769E" -> "786E" [ color="purple",arrowhead="none" ]; +"769E" -> "787E" [ color="purple",arrowhead="none" ]; +"770E" -> "788E" [ color="purple",arrowhead="none" ]; +"770E" -> "789E" [ color="purple",arrowhead="none" ]; +"769E" -> "790E" [ color="purple",arrowhead="none" ]; +"770E" -> "791E" [ color="purple",arrowhead="none" ]; +"769E" -> "792E" [ color="purple",arrowhead="none" ]; +"793E" -> "769E" [ color="purple",arrowhead="none" ]; +"769E" -> "784E" [ color="purple",arrowhead="none" ]; +"770E" -> "785E" [ color="purple",arrowhead="none" ]; +"788E" -> "787E" [ color="purple",arrowhead="none" ]; +"770E" -> "792E" [ color="purple",arrowhead="none" ]; +"798E" -> "799E" [ color="purple",arrowhead="none" ]; +"796E" -> "797E" [ color="purple",arrowhead="none" ]; +"793E" -> "789E" [ color="purple",arrowhead="none" ]; +"783E" -> "787E" [ color="purple",arrowhead="none" ]; +"784E" -> "792E" [ color="purple",arrowhead="none" ]; +"787E" -> "789E" [ color="purple",arrowhead="none" ]; +"769E" -> "791E" [ color="purple",arrowhead="none" ]; +"802E" -> "801E" [ color="purple",arrowhead="none" ]; +} diff --git a/dot/6.dot b/dot/6.dot new file mode 100644 index 0000000..0189738 --- /dev/null +++ b/dot/6.dot @@ -0,0 +1,2140 @@ +/* contributed by Sancho Lerena, http://pandorafms.org + +About the graph: this is an automated network map generated with Pandora +FMS, this map is a visual representation of the network discovery done by +the recon server, which sweeps the network, and identify hosts in a network +and the full chain of hosts in the route to discovered networks. + +command: + +twopi -Tcmapx -onetworkmap_twopi_1.map -Tpng -onetworkmap_twopi.png networkmap_twopi.gv.txt + +*/ + +graph networkmap { labeljust=l; margin=0; ratio=fill;root=0;size="8,5.4";300 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
109.217.106.212.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=300", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=300"]; + 619 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
192.36.144.230
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=619", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=619"]; + 686 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.0.255
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=686", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=686"]; + 620 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.0.53
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=620", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=620"]; + 692 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=692", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=692"]; + 699 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.10
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=699", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=699"]; + 700 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.12
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=700", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=700"]; + 701 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.13
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=701", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=701"]; + 702 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=702", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=702"]; + 703 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.15
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=703", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=703"]; + 704 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.16
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=704", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=704"]; + 705 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=705", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=705"]; + 706 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.18
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=706", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=706"]; + 707 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.19
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=707", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=707"]; + 694 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.2
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=694", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=694"]; + 708 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.20
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=708", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=708"]; + 709 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.21
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=709", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=709"]; + 710 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.22
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=710", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=710"]; + 711 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.23
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=711", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=711"]; + 712 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.24
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=712", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=712"]; + 791 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.240
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=791", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=791"]; + 792 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.253
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=792", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=792"]; + 713 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.26
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=713", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=713"]; + 714 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.27
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=714", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=714"]; + 715 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.28
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=715", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=715"]; + 716 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.29
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=716", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=716"]; + 695 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.3
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=695", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=695"]; + 717 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.30
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=717", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=717"]; + 718 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.31
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=718", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=718"]; + 719 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.36
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=719", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=719"]; + 696 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.4
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=696", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=696"]; + 697 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.7
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=697", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=697"]; + 698 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.1.9
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=698", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=698"]; + 793 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=793", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=793"]; + 798 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.10
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=798", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=798"]; + 799 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.12
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=799", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=799"]; + 800 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.13
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=800", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=800"]; + 801 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=801", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=801"]; + 802 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.15
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=802", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=802"]; + 803 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.16
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=803", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=803"]; + 804 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=804", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=804"]; + 805 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.18
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=805", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=805"]; + 806 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.19
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=806", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=806"]; + 794 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.2
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=794", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=794"]; + 807 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.20
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=807", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=807"]; + 795 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.5
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=795", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=795"]; + 796 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.6
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=796", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=796"]; + 797 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.2.7
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=797", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=797"]; + 813 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
194.0.3.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=813", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=813"]; + 690 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.187.255.152
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=690", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=690"]; + 689 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.187.255.156
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=689", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=689"]; + 691 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.187.255.161
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=691", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=691"]; + 533 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.66.224.76
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=533", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=533"]; + 538 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.66.224.76
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=538", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=538"]; + 570 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.66.225.69
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=570", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=570"]; + 616 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
195.69.119.172
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=616", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=616"]; + 581 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
204.15.20.35
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=581", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=581"]; + 647 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
204.15.22.245
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=647", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=647"]; + 577 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
204.15.23.111
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=577", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=577"]; + 557 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.100
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=557", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=557"]; + 558 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.101
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=558", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=558"]; + 560 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.102
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=560", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=560"]; + 562 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.104
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=562", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=562"]; + 568 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.109
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=568", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=568"]; + 425 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=425", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=425"]; + 426 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.16
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=426", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=426"]; + 427 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.18
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=427", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=427"]; + 428 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.19
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=428", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=428"]; + 430 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.27
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=430", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=430"]; + 431 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.32
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=431", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=431"]; + 432 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.33
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=432", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=432"]; + 433 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.34
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=433", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=433"]; + 434 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.35
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=434", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=434"]; + 435 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.36
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=435", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=435"]; + 436 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.37
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=436", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=436"]; + 437 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.38
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=437", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=437"]; + 445 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.39
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=445", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=445"]; + 419 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.4
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=419", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=419"]; + 447 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.40
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=447", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=447"]; + 449 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.41
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=449", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=449"]; + 451 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.42
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=451", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=451"]; + 452 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.43
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=452", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=452"]; + 454 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.44
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=454", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=454"]; + 456 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.45
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=456", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=456"]; + 458 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.46
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=458", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=458"]; + 460 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.47
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=460", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=460"]; + 462 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.48
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=462", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=462"]; + 464 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.49
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=464", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=464"]; + 422 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.5
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=422", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=422"]; + 466 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.50
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=466", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=466"]; + 468 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.51
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=468", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=468"]; + 470 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.52
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=470", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=470"]; + 472 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.53
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=472", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=472"]; + 474 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.54
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=474", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=474"]; + 476 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.56
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=476", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=476"]; + 478 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.57
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=478", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=478"]; + 479 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.58
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=479", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=479"]; + 481 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.59
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=481", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=481"]; + 423 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.6
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=423", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=423"]; + 483 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.60
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=483", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=483"]; + 484 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.61
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=484", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=484"]; + 485 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.62
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=485", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=485"]; + 487 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.63
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=487", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=487"]; + 489 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.64
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=489", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=489"]; + 491 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.65
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=491", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=491"]; + 493 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.66
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=493", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=493"]; + 496 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.68
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=496", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=496"]; + 498 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.69
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=498", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=498"]; + 502 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.72
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=502", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=502"]; + 504 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.73
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=504", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=504"]; + 505 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.74
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=505", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=505"]; + 507 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.75
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=507", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=507"]; + 509 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.76
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=509", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=509"]; + 511 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.77
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=511", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=511"]; + 513 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.78
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=513", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=513"]; + 515 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.79
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=515", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=515"]; + 517 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.81
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=517", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=517"]; + 518 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.82
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=518", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=518"]; + 519 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.83
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=519", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=519"]; + 521 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.84
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=521", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=521"]; + 523 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.85
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=523", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=523"]; + 525 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.86
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=525", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=525"]; + 527 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.87
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=527", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=527"]; + 529 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.88
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=529", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=529"]; + 531 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.89
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=531", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=531"]; + 542 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.91
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=542", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=542"]; + 544 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.93
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=544", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=544"]; + 547 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.95
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=547", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=547"]; + 549 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.96
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=549", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=549"]; + 551 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.97
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=551", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=551"]; + 553 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.98
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=553", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=553"]; + 555 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.229.99
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=555", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=555"]; + 421 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.243.73
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=421", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=421"]; + 418 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.243.77
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=418", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=418"]; + 429 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.243.81
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=429", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=429"]; + 424 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.243.85
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=424", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=424"]; + 415 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.251.200
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=415", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=415"]; + 420 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
209.85.252.83
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=420", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=420"]; + 416 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
216.239.43.233
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=416", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=416"]; + 414 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
216.239.49.196
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=414", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=414"]; + 417 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
216.239.49.45
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=417", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=417"]; + 808 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
62.40.112.122
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=808", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=808"]; + 809 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
62.40.112.206
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=809", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=809"]; + 810 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
62.40.125.158
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=810", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=810"]; + 534 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.27.149
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=534", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=534"]; + 539 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.27.149
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=539", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=539"]; + 536 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.29.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=536", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=536"]; + 541 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.29.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=541", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=541"]; + 535 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.31.186
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=535", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=535"]; + 540 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
64.125.31.186
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=540", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=540"]; + 573 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=573", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=573"]; + 580 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.11
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=580", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=580"]; + 583 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.13
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=583", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=583"]; + 585 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=585", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=585"]; + 587 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.15
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=587", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=587"]; + 612 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.150
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=612", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=612"]; + 613 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.151
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=613", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=613"]; + 614 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.152
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=614", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=614"]; + 615 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.153
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=615", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=615"]; + 588 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=588", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=588"]; + 590 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.18
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=590", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=590"]; + 592 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.19
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=592", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=592"]; + 574 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.2
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=574", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=574"]; + 593 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.21
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=593", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=593"]; + 594 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.22
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=594", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=594"]; + 595 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.23
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=595", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=595"]; + 621 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.231
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=621", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=621"]; + 622 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.232
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=622", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=622"]; + 623 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.233
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=623", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=623"]; + 624 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.234
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=624", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=624"]; + 625 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.244
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=625", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=625"]; + 626 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.245
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=626", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=626"]; + 627 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.246
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=627", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=627"]; + 628 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.247
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=628", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=628"]; + 629 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.248
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=629", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=629"]; + 630 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.249
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=630", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=630"]; + 596 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.25
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=596", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=596"]; + 631 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.250
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=631", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=631"]; + 632 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.251
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=632", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=632"]; + 633 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.252
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=633", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=633"]; + 634 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.253
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=634", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=634"]; + 635 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.254
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=635", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=635"]; + 597 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.26
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=597", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=597"]; + 599 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.27
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=599", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=599"]; + 600 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.28
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=600", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=600"]; + 601 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.29
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=601", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=601"]; + 602 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.30
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=602", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=602"]; + 604 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.31
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=604", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=604"]; + 605 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.32
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=605", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=605"]; + 606 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.33
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=606", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=606"]; + 607 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.34
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=607", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=607"]; + 608 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.35
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=608", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=608"]; + 609 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.36
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=609", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=609"]; + 610 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.37
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=610", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=610"]; + 611 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.38
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=611", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=611"]; + 576 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.5
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=576", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=576"]; + 578 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.153.6
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=578", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=578"]; + 636 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.33
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=636", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=636"]; + 638 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.34
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=638", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=638"]; + 639 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.35
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=639", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=639"]; + 640 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.36
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=640", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=640"]; + 641 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.49
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=641", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=641"]; + 643 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.50
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=643", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=643"]; + 644 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.51
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=644", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=644"]; + 645 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.154.52
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=645", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=645"]; + 646 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=646", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=646"]; + 654 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.10
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=654", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=654"]; + 720 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.105
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=720", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=720"]; + 721 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.106
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=721", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=721"]; + 656 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.11
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=656", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=656"]; + 723 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.116
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=723", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=723"]; + 724 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.117
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=724", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=724"]; + 725 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.118
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=725", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=725"]; + 726 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.119
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=726", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=726"]; + 658 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.12
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=658", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=658"]; + 727 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.120
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=727", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=727"]; + 728 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.121
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=728", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=728"]; + 729 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.122
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=729", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=729"]; + 730 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.123
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=730", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=730"]; + 731 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.124
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=731", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=731"]; + 732 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.125
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=732", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=732"]; + 733 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.126
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=733", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=733"]; + 734 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.129
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=734", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=734"]; + 660 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.13
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=660", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=660"]; + 735 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.130
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=735", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=735"]; + 736 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.133
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=736", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=736"]; + 737 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.134
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=737", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=737"]; + 738 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.135
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=738", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=738"]; + 739 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.136
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=739", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=739"]; + 740 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.137
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=740", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=740"]; + 741 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.138
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=741", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=741"]; + 742 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.139
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=742", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=742"]; + 661 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=661", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=661"]; + 743 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.140
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=743", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=743"]; + 744 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.141
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=744", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=744"]; + 745 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.142
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=745", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=745"]; + 746 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.143
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=746", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=746"]; + 747 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.144
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=747", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=747"]; + 748 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.145
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=748", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=748"]; + 749 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.146
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=749", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=749"]; + 750 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.147
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=750", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=750"]; + 751 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.148
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=751", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=751"]; + 752 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.149
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=752", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=752"]; + 662 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.15
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=662", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=662"]; + 753 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.150
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=753", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=753"]; + 754 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.151
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=754", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=754"]; + 755 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.152
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=755", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=755"]; + 756 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.153
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=756", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=756"]; + 757 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.154
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=757", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=757"]; + 758 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.155
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=758", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=758"]; + 759 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.156
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=759", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=759"]; + 760 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.157
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=760", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=760"]; + 761 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.158
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=761", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=761"]; + 762 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.159
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=762", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=762"]; + 664 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.16
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=664", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=664"]; + 763 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.160
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=763", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=763"]; + 764 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.161
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=764", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=764"]; + 765 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.162
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=765", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=765"]; + 766 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.163
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=766", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=766"]; + 767 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.164
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=767", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=767"]; + 768 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.165
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=768", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=768"]; + 769 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.166
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=769", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=769"]; + 770 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.167
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=770", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=770"]; + 771 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.168
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=771", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=771"]; + 772 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.169
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=772", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=772"]; + 665 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.17
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=665", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=665"]; + 773 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.170
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=773", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=773"]; + 774 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.171
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=774", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=774"]; + 775 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.172
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=775", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=775"]; + 776 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.173
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=776", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=776"]; + 777 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.174
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=777", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=777"]; + 778 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.175
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=778", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=778"]; + 779 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.176
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=779", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=779"]; + 780 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.177
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=780", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=780"]; + 781 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.178
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=781", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=781"]; + 782 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.179
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=782", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=782"]; + 666 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.18
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=666", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=666"]; + 783 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.180
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=783", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=783"]; + 784 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.181
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=784", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=784"]; + 785 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.182
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=785", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=785"]; + 786 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.183
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=786", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=786"]; + 667 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.19
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=667", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=667"]; + 649 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.2
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=649", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=649"]; + 668 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.20
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=668", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=668"]; + 669 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.21
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=669", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=669"]; + 670 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.22
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=670", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=670"]; + 671 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.23
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=671", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=671"]; + 787 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.234
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=787", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=787"]; + 672 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.24
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=672", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=672"]; + 788 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.241
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=788", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=788"]; + 789 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.242
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=789", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=789"]; + 790 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.243
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=790", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=790"]; + 673 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.25
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=673", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=673"]; + 674 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.26
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=674", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=674"]; + 676 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.27
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=676", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=676"]; + 677 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.28
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=677", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=677"]; + 678 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.29
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=678", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=678"]; + 679 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.43
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=679", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=679"]; + 680 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.44
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=680", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=680"]; + 650 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.5
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=650", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=650"]; + 681 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.52
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=681", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=681"]; + 682 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.53
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=682", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=682"]; + 683 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.54
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=683", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=683"]; + 684 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.55
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=684", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=684"]; + 685 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.56
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=685", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=685"]; + 652 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.6
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=652", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=652"]; + 693 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.220.155.63
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=693", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=693"]; + 438 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.33.201.221
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=438", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=438"]; + 439 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
66.33.201.66
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=439", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=439"]; + 359 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=359", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=359"]; + 366 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.10
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=366", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=366"]; + 516 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.101
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=516", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=516"]; + 520 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.102
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=520", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=520"]; + 522 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.103
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=522", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=522"]; + 524 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.104
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=524", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=524"]; + 526 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.105
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=526", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=526"]; + 528 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.106
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=528", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=528"]; + 530 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.107
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=530", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=530"]; + 532 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.108
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=532", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=532"]; + 537 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.109
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=537", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=537"]; + 367 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.11
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=367", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=367"]; + 543 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.110
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=543", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=543"]; + 545 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.111
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=545", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=545"]; + 546 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.112
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=546", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=546"]; + 548 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.113
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=548", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=548"]; + 550 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.114
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=550", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=550"]; + 391 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.36
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=391", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=391"]; + 392 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.37
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=392", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=392"]; + 393 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.38
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=393", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=393"]; + 394 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.39
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=394", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=394"]; + 360 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.4
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=360", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=360"]; + 395 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.40
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=395", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=395"]; + 396 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.41
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=396", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=396"]; + 397 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.42
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=397", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=397"]; + 398 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.44
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=398", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=398"]; + 399 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.45
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=399", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=399"]; + 400 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.163.176.46
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=400", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=400"]; + 301 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
69.216.106.212.s
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=301", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=301"]; + 657 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.193
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=657", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=657"]; + 651 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.215
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=651", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=651"]; + 655 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.217
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=655", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=655"]; + 659 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.219
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=659", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=659"]; + 663 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.221
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=663", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=663"]; + 653 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.223
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=653", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=653"]; + 722 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.225
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=722", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=722"]; + 675 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.227
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=675", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=675"]; + 579 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.237
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=579", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=579"]; + 591 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.239
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=591", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=591"]; + 603 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.245
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=603", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=603"]; + 589 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.247
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=589", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=589"]; + 575 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.77
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=575", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=575"]; + 572 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.76.79
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=572", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=572"]; + 637 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.142
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=637", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=637"]; + 642 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.144
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=642", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=642"]; + 582 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.77
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=582", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=582"]; + 584 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.79
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=584", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=584"]; + 586 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.81
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=586", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=586"]; + 598 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.77.83
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=598", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=598"]; + 571 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.78.182
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=571", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=571"]; + 648 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
74.119.78.83
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=648", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=648"]; + 618 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
77.72.228.14
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=618", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=618"]; + 617 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
77.72.228.45
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=617", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=617"]; + 688 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
84.233.213.222
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=688", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=688"]; + 687 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
84.233.213.41
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=687", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=687"]; + 812 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
85.254.196.210
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=812", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=812"]; + 811 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
85.254.196.237
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=811", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=811"]; + 331 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.31
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=331", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=331"]; + 332 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.32
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=332", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=332"]; + 333 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.33
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=333", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=333"]; + 334 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.34
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=334", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=334"]; + 335 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.35
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=335", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=335"]; + 336 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.38
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=336", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=336"]; + 337 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.39
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=337", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=337"]; + 338 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.40
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=338", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=338"]; + 339 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.41
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=339", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=339"]; + 340 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.42
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=340", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=340"]; + 341 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.43
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=341", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=341"]; + 342 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.44
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=342", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=342"]; + 343 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.45
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=343", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=343"]; + 344 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.46
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=344", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=344"]; + 345 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.47
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=345", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=345"]; + 346 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.48
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=346", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=346"]; + 347 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.49
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=347", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=347"]; + 348 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.50
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=348", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=348"]; + 349 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.51
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=349", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=349"]; + 350 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.52
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=350", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=350"]; + 351 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.53
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=351", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=351"]; + 352 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.56
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=352", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=352"]; + 353 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.57
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=353", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=353"]; + 354 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.58
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=354", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=354"]; + 355 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.59
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=355", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=355"]; + 356 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.60
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=356", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=356"]; + 357 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.61
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=357", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=357"]; + 358 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
87.248.112.62
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=358", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=358"]; + 306 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
unknown-66-196-6
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=306", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=306"]; + 319 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
unknown-87-248-1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=319", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=319"]; + 320 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
unknown-87-248-1
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=320", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=320"]; + 304 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
ae-1.msr1.ird.ya
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=304", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=304"]; + 307 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
ae-2.msr2.ird.ya
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=307", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=307"]; + 316 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
fe.gsp.search.vi
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=316", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=316"]; + 302 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
ge-1-1-0.pat1.th
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=302", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=302"]; + 305 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
ha1.vl-220.bas-b
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=305", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=305"]; + 308 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
ha2.vl-220.bas-b
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=308", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=308"]; + 1 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
metafora
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=1", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=1"]; + 2 [ color="#FF1D1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
metafora.artica.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=2", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=2"]; + 325 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
p1.movies.ird.ya
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=325", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=325"]; + 323 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
p1.tv.ird.yahoo.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=323", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=323"]; + 330 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
p2.movies.ird.ya
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=330", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=330"]; + 329 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
p2.tv.ird.yahoo.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=329", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=329"]; + 321 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
p4.tv.ird.yahoo.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=321", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=321"]; + 322 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
qa-eu.ent.ird.ya
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=322", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=322"]; + 315 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
rd.gsp.search.vi
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=315", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=315"]; + 326 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
rd01.gsp.search.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=326", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=326"]; + 327 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
rd02.gsp.search.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=327", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=327"]; + 328 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
rd03.gsp.search.
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=328", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=328"]; + 312 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
si-b34.vrrp.vl22
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=312", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=312"]; + 303 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
so-0-0-0.pat1.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=303", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=303"]; + 314 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
te-7-4.bas-b1.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=314", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=314"]; + 317 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
te-7-4.bas-b2.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=317", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=317"]; + 324 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
te-8-4.bas-b1.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=324", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=324"]; + 311 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
te-8-4.bas-b2.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=311", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=311"]; + 309 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
vl-220.bas-b1.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=309", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=309"]; + 310 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
vl-220.bas-b2.ir
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=310", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=310"]; + 313 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
yts1.yql.ird.yah
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=313", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=313"]; + 318 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< +
z6po-feeder.sear
>, + shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=318", + tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=318"]; + 619 -- 618[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=619&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];686 -- 618[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=686&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];620 -- 619[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=620&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];692 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=692&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];699 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=699&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];700 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=700&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];701 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=701&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];702 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=702&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];703 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=703&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];704 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=704&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];705 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=705&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];706 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=706&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];707 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=707&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];694 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=694&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];708 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=708&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];709 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=709&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];710 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=710&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];711 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=711&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];712 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=712&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];791 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=791&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];792 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=792&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];713 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=713&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];714 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=714&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];715 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=715&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];716 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=716&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];695 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=695&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];717 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=717&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];718 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=718&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];719 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=719&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];696 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=696&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];697 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=697&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];698 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=698&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];793 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=793&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];798 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=798&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];799 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=799&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];800 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=800&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];801 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=801&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];802 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=802&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];803 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=803&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];804 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=804&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];805 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=805&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];806 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=806&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];794 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=794&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];807 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=807&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];795 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=795&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];796 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=796&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];797 -- 691[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=797&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];813 -- 812[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=813&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];690 -- 689[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=690&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];689 -- 688[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=689&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];691 -- 690[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=691&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];533 -- 301[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=533&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];538 -- 301[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=538&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];570 -- 301[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=570&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];581 -- 571[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=581&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];647 -- 570[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=647&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];577 -- 571[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=577&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];557 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=557&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];558 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=558&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];560 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=560&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];562 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=562&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];568 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=568&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];425 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=425&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];426 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=426&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];427 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=427&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];428 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=428&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];430 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=430&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];431 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=431&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];432 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=432&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];433 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=433&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];434 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=434&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];435 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=435&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];436 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=436&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];437 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=437&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];445 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=445&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];419 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=419&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];447 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=447&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];449 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=449&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];451 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=451&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];452 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=452&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];454 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=454&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];456 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=456&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];458 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=458&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];460 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=460&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];462 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=462&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];464 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=464&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];422 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=422&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];466 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=466&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];468 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=468&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];470 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=470&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];472 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=472&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];474 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=474&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];476 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=476&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];478 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=478&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];479 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=479&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];481 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=481&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];423 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=423&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];483 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=483&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];484 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=484&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];485 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=485&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];487 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=487&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];489 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=489&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];491 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=491&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];493 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=493&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];496 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=496&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];498 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=498&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];502 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=502&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];504 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=504&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];505 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=505&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];507 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=507&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];509 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=509&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];511 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=511&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];513 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=513&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];515 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=515&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];517 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=517&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];518 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=518&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];519 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=519&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];521 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=521&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];523 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=523&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];525 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=525&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];527 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=527&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];529 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=529&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];531 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=531&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];542 -- 541[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=542&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];544 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=544&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];547 -- 429[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=547&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];549 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=549&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];551 -- 424[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=551&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];553 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=553&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];555 -- 418[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=555&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];421 -- 420[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=421&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];418 -- 417[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=418&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];429 -- 417[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=429&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];424 -- 420[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=424&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];415 -- 414[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=415&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];420 -- 416[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=420&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];416 -- 415[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=416&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];417 -- 416[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=417&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];809 -- 808[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=809&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];810 -- 809[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=810&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];534 -- 533[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=534&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];539 -- 538[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=539&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];536 -- 535[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=536&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];541 -- 540[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=541&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];535 -- 534[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=535&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];540 -- 539[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=540&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];573 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=573&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];580 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=580&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];583 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=583&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];585 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=585&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];587 -- 586[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=587&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];612 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=612&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];613 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=613&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];614 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=614&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];615 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=615&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];588 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=588&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];590 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=590&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];592 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=592&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];574 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=574&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];593 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=593&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];594 -- 586[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=594&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];595 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=595&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];621 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=621&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];622 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=622&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];623 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=623&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];624 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=624&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];625 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=625&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];626 -- 598[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=626&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];627 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=627&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];628 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=628&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];629 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=629&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];630 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=630&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];596 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=596&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];631 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=631&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];632 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=632&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];633 -- 598[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=633&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];634 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=634&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];635 -- 586[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=635&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];597 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=597&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];599 -- 598[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=599&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];600 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=600&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];601 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=601&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];602 -- 584[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=602&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];604 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=604&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];605 -- 589[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=605&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];606 -- 603[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=606&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];607 -- 579[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=607&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];608 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=608&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];609 -- 591[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=609&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];610 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=610&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];611 -- 582[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=611&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];576 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=576&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];578 -- 577[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=578&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];636 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=636&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];638 -- 637[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=638&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];639 -- 637[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=639&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];640 -- 637[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=640&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];641 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=641&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];643 -- 642[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=643&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];644 -- 642[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=644&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];645 -- 642[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=645&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];646 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=646&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];654 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=654&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];720 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=720&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];721 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=721&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];656 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=656&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];723 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=723&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];724 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=724&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];725 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=725&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];726 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=726&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];658 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=658&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];727 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=727&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];728 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=728&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];729 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=729&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];730 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=730&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];731 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=731&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];732 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=732&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];733 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=733&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];734 -- 648[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=734&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];660 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=660&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];735 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=735&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];736 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=736&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];737 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=737&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];738 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=738&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];739 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=739&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];740 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=740&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];741 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=741&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];742 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=742&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];661 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=661&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];743 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=743&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];744 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=744&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];745 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=745&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];746 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=746&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];747 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=747&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];748 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=748&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];749 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=749&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];750 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=750&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];751 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=751&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];752 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=752&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];662 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=662&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];753 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=753&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];754 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=754&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];755 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=755&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];756 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=756&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];757 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=757&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];758 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=758&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];759 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=759&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];760 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=760&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];761 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=761&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];762 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=762&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];664 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=664&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];763 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=763&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];764 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=764&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];765 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=765&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];766 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=766&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];767 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=767&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];768 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=768&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];769 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=769&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];770 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=770&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];771 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=771&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];772 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=772&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];665 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=665&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];773 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=773&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];774 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=774&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];775 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=775&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];776 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=776&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];777 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=777&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];778 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=778&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];779 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=779&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];780 -- 722[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=780&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];781 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=781&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];782 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=782&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];666 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=666&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];783 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=783&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];784 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=784&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];785 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=785&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];786 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=786&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];667 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=667&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];649 -- 648[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=649&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];668 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=668&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];669 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=669&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];670 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=670&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];671 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=671&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];787 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=787&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];672 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=672&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];788 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=788&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];789 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=789&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];790 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=790&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];673 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=673&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];674 -- 657[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=674&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];676 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=676&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];677 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=677&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];678 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=678&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];679 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=679&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];680 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=680&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];650 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=650&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];681 -- 653[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=681&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];682 -- 659[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=682&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];683 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=683&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];684 -- 675[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=684&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];685 -- 655[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=685&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];652 -- 651[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=652&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];693 -- 663[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=693&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];439 -- 359[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=439&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];359 -- 438[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=359&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];366 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=366&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];516 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=516&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];522 -- 421[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=522&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];524 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=524&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];526 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=526&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];528 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=528&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];530 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=530&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];532 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=532&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];537 -- 536[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=537&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];367 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=367&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];543 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=543&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];545 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=545&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];546 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=546&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];548 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=548&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];550 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=550&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];391 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=391&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];392 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=392&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];393 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=393&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];394 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=394&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];360 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=360&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];395 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=395&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];396 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=396&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];397 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=397&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];398 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=398&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];399 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=399&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];400 -- 439[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=400&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];301 -- 300[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=301&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];657 -- 581[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=657&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];651 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=651&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];655 -- 577[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=655&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];659 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=659&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];663 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=663&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];653 -- 648[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=653&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];722 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=722&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];675 -- 577[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=675&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];579 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=579&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];591 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=591&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];603 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=603&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];589 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=589&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];575 -- 571[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=575&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];572 -- 571[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=572&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];637 -- 575[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=637&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];642 -- 572[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=642&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];582 -- 581[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=582&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];584 -- 577[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=584&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];586 -- 581[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=586&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];598 -- 577[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=598&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];571 -- 570[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=571&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];648 -- 647[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=648&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];618 -- 617[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=618&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];617 -- 616[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=617&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];688 -- 687[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=688&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];812 -- 811[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=812&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];811 -- 810[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=811&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];331 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=331&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];332 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=332&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];333 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=333&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];334 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=334&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];335 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=335&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];336 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=336&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];337 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=337&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];338 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=338&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];339 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=339&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];340 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=340&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];341 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=341&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];342 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=342&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];343 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=343&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];344 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=344&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];345 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=345&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];346 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=346&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];347 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=347&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];348 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=348&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];349 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=349&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];350 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=350&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];351 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=351&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];352 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=352&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];353 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=353&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];354 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=354&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];355 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=355&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];356 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=356&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];357 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=357&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];358 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=358&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];306 -- 302[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=306&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];319 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=319&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];320 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=320&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];304 -- 303[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=304&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];307 -- 306[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=307&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];316 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=316&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];302 -- 301[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=302&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];305 -- 304[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=305&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];308 -- 307[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=308&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];325 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=325&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];323 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=323&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];330 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=330&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];329 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=329&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];321 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=321&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];322 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=322&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];315 -- 314[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=315&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];326 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=326&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];327 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=327&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];328 -- 324[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=328&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];312 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=312&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];303 -- 302[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=303&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];314 -- 307[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=314&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];317 -- 307[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=317&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];324 -- 304[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=324&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];311 -- 304[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=311&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];309 -- 307[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=309&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];310 -- 307[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=310&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];313 -- 311[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=313&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];318 -- 317[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=318&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 [ color="#364D1F", fontsize=12, style="filled", fixedsize=true, width=0.8, height=0.6, label=<
Pandora FMS
>, + shape="ellipse", URL="index.php?sec=estado&sec2=operation/agentes/group_view" ];0 -- 300[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 616[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 414[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 808[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 438[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 520[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 687[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 1[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 2[color="#BDBDBD", headclip=false, tailclip=false, + edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];} \ No newline at end of file diff --git a/dot/Ast.java b/dot/Ast.java new file mode 100644 index 0000000..7b020df --- /dev/null +++ b/dot/Ast.java @@ -0,0 +1,46 @@ +import java.util.Map; +import java.util.LinkedList; +import java.util.Formatter; +import java.util.Locale; +import java.util.ArrayList; +class Ast implements AstNode { + private String name; + private Map attributes; + Ast(String name, Map attributes) { + this.name = name; + this.attributes = attributes; + } + public AstNode getAttribute(String name) { + return this.attributes.get(name); + } + public Map getAttributes() { + return this.attributes; + } + public String getName() { + return this.name; + } + public String toString() { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + LinkedList attributes = new LinkedList(); + for (final Map.Entry attribute : this.attributes.entrySet()) { + final String name = attribute.getKey(); + final AstNode node = attribute.getValue(); + final String nodeStr = (node == null) ? "None" : node.toString(); + attributes.add(name + "=" + nodeStr); + } + formatter.format("(%s: %s)", this.name, Utility.join(attributes, ", ")); + return formatter.toString(); + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + ArrayList children = new ArrayList(); + for( Map.Entry attribute : this.attributes.entrySet() ) { + String valueString = attribute.getValue() == null ? "None" : attribute.getValue().toPrettyString(indent + 2).trim(); + children.add(spaces + " " + attribute.getKey() + "=" + valueString); + } + return spaces + "(" + this.name + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; + } +} diff --git a/dot/AstList.java b/dot/AstList.java new file mode 100644 index 0000000..220d2e1 --- /dev/null +++ b/dot/AstList.java @@ -0,0 +1,20 @@ +import java.util.ArrayList; +class AstList extends ArrayList implements AstNode { + public String toString() { + return "[" + Utility.join(this, ", ") + "]"; + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + if (this.size() == 0) { + return spaces + "[]"; + } + ArrayList elements = new ArrayList(); + for ( AstNode node : this ) { + elements.add(node.toPrettyString(indent + 2)); + } + return spaces + "[\n" + Utility.join(elements, ",\n") + "\n" + spaces + "]"; + } +} diff --git a/dot/AstNode.java b/dot/AstNode.java new file mode 100644 index 0000000..5e30462 --- /dev/null +++ b/dot/AstNode.java @@ -0,0 +1,5 @@ +interface AstNode { + public String toString(); + public String toPrettyString(); + public String toPrettyString(int indent); +} diff --git a/dot/AstTransform.java b/dot/AstTransform.java new file mode 100644 index 0000000..f01ae0c --- /dev/null +++ b/dot/AstTransform.java @@ -0,0 +1 @@ +interface AstTransform {} diff --git a/dot/AstTransformNodeCreator.java b/dot/AstTransformNodeCreator.java new file mode 100644 index 0000000..f708c21 --- /dev/null +++ b/dot/AstTransformNodeCreator.java @@ -0,0 +1,24 @@ +import java.util.LinkedList; +import java.util.Map; +import java.util.LinkedHashMap; +class AstTransformNodeCreator implements AstTransform { + private String name; + private LinkedHashMap parameters; + AstTransformNodeCreator(String name, LinkedHashMap parameters) { + this.name = name; + this.parameters = parameters; + } + public Map getParameters() { + return this.parameters; + } + public String getName() { + return this.name; + } + public String toString() { + LinkedList items = new LinkedList(); + for (final Map.Entry entry : this.parameters.entrySet()) { + items.add(entry.getKey() + "=$" + entry.getValue().toString()); + } + return "AstNodeCreator: " + this.name + "( " + Utility.join(items, ", ") + " )"; + } +} diff --git a/dot/AstTransformSubstitution.java b/dot/AstTransformSubstitution.java new file mode 100644 index 0000000..404b7bd --- /dev/null +++ b/dot/AstTransformSubstitution.java @@ -0,0 +1,12 @@ +class AstTransformSubstitution implements AstTransform { + private int index; + AstTransformSubstitution(int index) { + this.index = index; + } + public int getIndex() { + return this.index; + } + public String toString() { + return "AstSubstitution: $" + Integer.toString(this.index); + } +} diff --git a/dot/DotParser.java b/dot/DotParser.java new file mode 100644 index 0000000..0347416 --- /dev/null +++ b/dot/DotParser.java @@ -0,0 +1,957 @@ + +import java.util.*; +import java.util.HashMap; +import java.util.LinkedHashMap; +class DotParser implements Parser { + private TokenStream tokens; + private HashMap expressionParsers; + /* table[nonterminal][terminal] = rule */ + private static final int[][] table = { + { 30, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27 }, + { -1, 51, -1, -1, 44, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 39, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 24, -1, -1, -1, -1, -1, -1, -1, 10, 24, -1, 43, -1, 26, 10, -1, 24, 9, -1, -1 }, + { -1, -1, 40, -1, -1, -1, 40, 40, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, 40, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1 }, + { -1, -1, 33, -1, -1, -1, 37, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1 }, + { 4, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1 }, + { 35, -1, -1, -1, -1, -1, -1, -1, 35, 35, -1, 35, 11, 35, 35, -1, 35, 35, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1 }, + { 28, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1 }, + { 22, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, + { 23, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, 50, -1, -1, -1, -1, -1 }, + { -1, -1, 12, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 47, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, 0, -1, -1, -1, 5, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1 }, + { -1, -1, 18, -1, -1, -1, 18, 18, -1, -1, -1, -1, -1, -1, -1, 46, -1, -1, 18, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, 17, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + }; + public enum TerminalId { + TERMINAL_GRAPH(0, "graph"), + TERMINAL_RSQUARE(1, "rsquare"), + TERMINAL_SEMI(2, "semi"), + TERMINAL_DIGRAPH(3, "digraph"), + TERMINAL_ASSIGN(4, "assign"), + TERMINAL_COMMA(5, "comma"), + TERMINAL_ARROW(6, "arrow"), + TERMINAL_LSQUARE(7, "lsquare"), + TERMINAL_LBRACE(8, "lbrace"), + TERMINAL_EDGE(9, "edge"), + TERMINAL_IDENTIFIER(10, "identifier"), + TERMINAL_VALUE_ASSIGN_HINT(11, "value_assign_hint"), + TERMINAL_RBRACE(12, "rbrace"), + TERMINAL_EDGE_STMT_HINT(13, "edge_stmt_hint"), + TERMINAL_SUBGRAPH(14, "subgraph"), + TERMINAL_COLON(15, "colon"), + TERMINAL_NODE(16, "node"), + TERMINAL_NODE_STMT_HINT(17, "node_stmt_hint"), + TERMINAL_DASHDASH(18, "dashdash"), + TERMINAL_STRICT(19, "strict"); + private final int id; + private final String string; + TerminalId(int id, String string) { + this.id = id; + this.string = string; + } + public int id() {return id;} + public String string() {return string;} + } + private class DotTerminalMap implements TerminalMap { + private Map id_to_str; + private Map str_to_id; + DotTerminalMap(TerminalId[] terminals) { + id_to_str = new HashMap(); + str_to_id = new HashMap(); + for( TerminalId terminal : terminals ) { + Integer id = new Integer(terminal.id()); + String str = terminal.string(); + id_to_str.put(id, str); + str_to_id.put(str, id); + } + } + public int get(String string) { return this.str_to_id.get(string); } + public String get(int id) { return this.id_to_str.get(id); } + public boolean isValid(String string) { return this.str_to_id.containsKey(string); } + public boolean isValid(int id) { return this.id_to_str.containsKey(id); } + } + DotParser() { + this.expressionParsers = new HashMap(); + } + public TerminalMap getTerminalMap() { + return new DotTerminalMap(TerminalId.values()); + } + public ParseTree parse(TokenStream tokens) throws SyntaxError { + this.tokens = tokens; + ParseTree tree = this.parse_graph(); + if (this.tokens.current() != null) { + throw new SyntaxError("Finished parsing without consuming all tokens."); + } + return tree; + } + private boolean isTerminal(TerminalId terminal) { + return (0 <= terminal.id() && terminal.id() <= 19); + } + private boolean isNonTerminal(TerminalId terminal) { + return (20 <= terminal.id() && terminal.id() <= 50); + } + private boolean isTerminal(int terminal) { + return (0 <= terminal && terminal <= 19); + } + private boolean isNonTerminal(int terminal) { + return (20 <= terminal && terminal <= 50); + } + private ParseTree parse__gen0() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[0][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(20, "_gen0")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 0 || current.getId() == 3) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 27) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); + tree.add(next); + return tree; + } + return tree; + } + private ParseTree parse__gen6() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(21, "_gen6")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 5 || current.getId() == 1) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 44) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr_value_assign(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen5() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(22, "_gen5")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 1) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 48) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_attr_values(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_stmt() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "stmt")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_node_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_subgraph(); + tree.add( subtree); + return tree; + } + else if (rule == 24) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 26) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_edge_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 43) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 3); + parameters.put("key", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen10() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen10")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 7 || current.getId() == 18 || current.getId() == 6 || current.getId() == 2) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 49) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_port_compass_pt(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_port_compass_pt() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "port_compass_pt")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 7) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen8() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "_gen8")); + tree.setList("mlist"); + if ( current != null ) { + if (current.getId() == 7 || current.getId() == 2) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 37) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_edge_rhs(); + tree.add( subtree); + subtree = this.parse__gen8(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_attr_type() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "attr_type")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 1) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); + tree.add(next); + return tree; + } + else if (rule == 4) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + tree.add(next); + return tree; + } + else if (rule == 20) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen2() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen2")); + tree.setList("tlist"); + if ( current != null ) { + if (current.getId() == 12) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 35) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_stmt(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_subgraph_name() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "subgraph_name")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 2) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_node_id() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "node_id")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 16) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("port", 1); + tree.setAstTransformation(new AstTransformNodeCreator("NodeId", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen9(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen4() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 1) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 25) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr_values(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_node_stmt() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "node_stmt")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 32) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("attributes", 2); + parameters.put("id", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); + tree.add(next); + subtree = this.parse_node_id(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr_stmt() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "attr_stmt")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("values", 1); + parameters.put("type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); + subtree = this.parse_attr_type(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_graph_type() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "graph_type")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 22) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + tree.add(next); + return tree; + } + else if (rule == 36) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_subgraph() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "subgraph")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 13) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("statements", 2); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); + subtree = this.parse__gen11(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_graph() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "graph")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 23) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("strict", 0); + parameters.put("type", 1); + parameters.put("name", 2); + parameters.put("statements", 4); + tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); + subtree = this.parse__gen0(); + tree.add( subtree); + subtree = this.parse_graph_type(); + tree.add( subtree); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen11() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "_gen11")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 8) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 50) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_subgraph_name(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen3() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen3")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 2) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 6) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_edge_op() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "edge_op")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 8) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); + tree.add(next); + return tree; + } + else if (rule == 29) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_edge_stmt() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "edge_stmt")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 38) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("node", 1); + parameters.put("attributes", 3); + parameters.put("edges", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Edg", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); + tree.add(next); + subtree = this.parse_node_or_subgraph(); + tree.add( subtree); + subtree = this.parse__gen7(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen7() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "_gen7")); + tree.setList("mlist"); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_edge_rhs(); + tree.add( subtree); + subtree = this.parse__gen8(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "attr")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 3) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); + tree.add(next); + subtree = this.parse__gen4(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen1() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen1")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 8) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 42) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + return tree; + } + private ParseTree parse_node_or_subgraph() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "node_or_subgraph")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_node_id(); + tree.add( subtree); + return tree; + } + else if (rule == 5) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_subgraph(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_port() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "port")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 15) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + subtree = this.parse_port_sub(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_edge_rhs() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "edge_rhs")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 19) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("node", 1); + parameters.put("edge_type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); + subtree = this.parse_edge_op(); + tree.add( subtree); + subtree = this.parse_node_or_subgraph(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen9() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen9")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 7 || current.getId() == 18 || current.getId() == 6 || current.getId() == 2) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 46) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_port(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_port_sub() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "port_sub")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 17) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + else if (rule == 45) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("compass_point", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen10(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr_value_assign() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[29][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "attr_value_assign")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 14) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr_values() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[30][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "attr_values")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 21) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 1); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen6(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } +} diff --git a/dot/ExpressionParser.java b/dot/ExpressionParser.java new file mode 100644 index 0000000..7dfbd91 --- /dev/null +++ b/dot/ExpressionParser.java @@ -0,0 +1,3 @@ +interface ExpressionParser extends Parser { + ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; +} diff --git a/dot/Lexer.java b/dot/Lexer.java new file mode 100644 index 0000000..40297bb --- /dev/null +++ b/dot/Lexer.java @@ -0,0 +1,169 @@ +import java.util.regex.*; +import java.util.ArrayList; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.nio.*; +import java.nio.charset.*; +import java.nio.channels.*; + +class SourceCode { + private File source; + private String resource; + private String contents; + private int line; + private int col; + + SourceCode(String source, String resource) { + this.contents = source; + this.resource = resource; + this.line = 1; + this.col = 1; + } + + SourceCode(File source) throws IOException { + this(source, "utf-8", source.getCanonicalPath()); + } + + SourceCode(File source, String resource) throws IOException { + this(source, "utf-8", resource); + } + + SourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { + FileChannel channel = new FileInputStream(source).getChannel(); + MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); + Charset cs = Charset.forName(encoding); + CharsetDecoder cd = cs.newDecoder(); + CharBuffer cb = cd.decode(buffer); + this.contents = cb.toString(); + this.resource = resource; + this.line = 1; + this.col = 1; + } + + public void advance(int amount) { + String str = this.contents.substring(0, amount); + for ( byte b : str.getBytes() ) { + if ( b == (byte) '\n' || b == (byte) '\r' ) { + this.line++; + this.col = 1; + } else { + this.col++; + } + } + this.contents = this.contents.substring(amount); + } + + public String getString() { + return this.contents; + } + + public String getResource() { + return this.resource; + } + + public int getLine() { + return this.line; + } + + public int getCol() { + return this.col; + } +} + +class LexerMatch { + private Terminal terminal; + LexerMatch() { this.terminal = null; } + LexerMatch(Terminal terminal) { this.terminal = terminal; } + public Terminal getTerminal() { return this.terminal; } +} + +class TokenLexer { + private Pattern regex; + private DotParser.TerminalId terminal; + + TokenLexer(Pattern regex, DotParser.TerminalId terminal) { + this.regex = regex; + this.terminal = terminal; + } + + LexerMatch match(SourceCode source) { + Matcher m = this.regex.matcher(source.getString()); + System.out.println("["); + //System.out.println("[\n code='"+source.getString().trim()+"'"); + System.out.println(" pattern="+m.pattern()); + LexerMatch rval = null; + if ( m.find() ) { + System.out.println(" match"); + String sourceString = m.group(); + + if (this.terminal != null) + rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol())); + else + rval = new LexerMatch(); + + source.advance(sourceString.length()); + } + System.out.println("]"); + return rval; + } +} + +public class Lexer { + public static void main(String[] args) { + ArrayList regex = new ArrayList(); + regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_DIGRAPH) ); + regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_GRAPH) ); + regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_SUBGRAPH) ); + regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_STRICT) ); + regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_EDGE) ); + regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_NODE) ); + regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI) ); + regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE) ); + regex.add( new TokenLexer(Pattern.compile("^\\{"), DotParser.TerminalId.TERMINAL_LBRACE) ); + regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE) ); + regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE) ); + regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH) ); + regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW) ); + regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA) ); + regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON) ); + regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN) ); + regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\")|[-]?(\\.[0-9]+|[0-9]+(.[0-9]*)?)"), DotParser.TerminalId.TERMINAL_IDENTIFIER) ); + regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); + + if ( args.length < 1 ) { + System.err.println("Usage: Lexer "); + System.exit(-1); + } + + try { + SourceCode code = new SourceCode(new File(args[0])); + ArrayList terminal_strings = new ArrayList(); + boolean progress = true; + + while (progress) { + progress = false; + for ( TokenLexer lexer : regex ) { + LexerMatch match = lexer.match(code); + if (match != null) { + progress = true; + if (match.getTerminal() != null) { + terminal_strings.add( " " + match.getTerminal() ); + } + break; + } + } + } + + System.out.println("["); + System.out.println( Utility.join(terminal_strings, ",\n") ); + System.out.println("]"); + System.out.flush(); + } catch (IOException e) { + System.err.println(e); + System.exit(-1); + } + } +} diff --git a/dot/NonTerminal.java b/dot/NonTerminal.java new file mode 100644 index 0000000..b0b17e2 --- /dev/null +++ b/dot/NonTerminal.java @@ -0,0 +1,17 @@ +class NonTerminal { + private int id; + private String string; + NonTerminal(int id, String string) { + this.id = id; + this.string = string; + } + public int getId() { + return this.id; + } + public String getString() { + return this.string; + } + public String toString() { + return this.string; + } +} diff --git a/dot/ParseTree.java b/dot/ParseTree.java new file mode 100644 index 0000000..b7a7bda --- /dev/null +++ b/dot/ParseTree.java @@ -0,0 +1,159 @@ +import java.util.ArrayList; +import java.util.Map; +import java.util.List; +import java.util.LinkedHashMap; +class ParseTree implements ParseTreeNode { + private NonTerminal nonterminal; + private ArrayList children; + private boolean isExpr, isNud, isPrefix, isInfix, isExprNud; + private int nudMorphemeCount; + private Terminal listSeparator; + private String list; + private AstTransform astTransform; + ParseTree(NonTerminal nonterminal) { + this.nonterminal = nonterminal; + this.children = new ArrayList(); + this.astTransform = null; + this.isExpr = false; + this.isNud = false; + this.isPrefix = false; + this.isInfix = false; + this.isExprNud = false; + this.nudMorphemeCount = 0; + this.listSeparator = null; + this.list = ""; + } + public void setExpr(boolean value) { this.isExpr = value; } + public void setNud(boolean value) { this.isNud = value; } + public void setPrefix(boolean value) { this.isPrefix = value; } + public void setInfix(boolean value) { this.isInfix = value; } + public void setExprNud(boolean value) { this.isExprNud = value; } + public void setAstTransformation(AstTransform value) { this.astTransform = value; } + public void setNudMorphemeCount(int value) { this.nudMorphemeCount = value; } + public void setList(String value) { this.list = value; } + public void setListSeparator(Terminal value) { this.listSeparator = value; } + public int getNudMorphemeCount() { return this.nudMorphemeCount; } + public List getChildren() { return this.children; } + public boolean isInfix() { return this.isInfix; } + public boolean isPrefix() { return this.isPrefix; } + public boolean isExpr() { return this.isExpr; } + public boolean isNud() { return this.isNud; } + public boolean isExprNud() { return this.isExprNud; } + public void add(ParseTreeNode tree) { + if (this.children == null) { + this.children = new ArrayList(); + } + this.children.add(tree); + } + private boolean isCompoundNud() { + if ( this.children.size() > 0 && this.children.get(0) instanceof ParseTree ) { + ParseTree child = (ParseTree) this.children.get(0); + if ( child.isNud() && !child.isPrefix() && !this.isExprNud() && !this.isInfix() ) { + return true; + } + } + return false; + } + public AstNode toAst() { + if ( this.list == "slist" || this.list == "nlist" ) { + int offset = (this.children.size() > 0 && this.children.get(0) == this.listSeparator) ? 1 : 0; + AstList astList = new AstList(); + if ( this.children.size() == 0 ) { + return astList; + } + astList.add(this.children.get(offset).toAst()); + astList.addAll((AstList) this.children.get(offset + 1).toAst()); + return astList; + } else if ( this.list == "tlist" ) { + AstList astList = new AstList(); + if ( this.children.size() == 0 ) { + return astList; + } + astList.add(this.children.get(0).toAst()); + astList.addAll((AstList) this.children.get(2).toAst()); + return astList; + } else if ( this.list == "mlist" ) { + AstList astList = new AstList(); + int lastElement = this.children.size() - 1; + if ( this.children.size() == 0 ) { + return astList; + } + for (int i = 0; i < lastElement; i++) { + astList.add(this.children.get(i).toAst()); + } + astList.addAll((AstList) this.children.get(this.children.size() - 1).toAst()); + return astList; + } else if ( this.isExpr ) { + if ( this.astTransform instanceof AstTransformSubstitution ) { + AstTransformSubstitution astSubstitution = (AstTransformSubstitution) astTransform; + return this.children.get(astSubstitution.getIndex()).toAst(); + } else if ( this.astTransform instanceof AstTransformNodeCreator ) { + AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) this.astTransform; + LinkedHashMap parameters = new LinkedHashMap(); + ParseTreeNode child; + for ( final Map.Entry parameter : astNodeCreator.getParameters().entrySet() ) { + String name = parameter.getKey(); + int index = parameter.getValue().intValue(); + if ( index == '$' ) { + child = this.children.get(0); + } else if ( this.isCompoundNud() ) { + ParseTree firstChild = (ParseTree) this.children.get(0); + if ( index < firstChild.getNudMorphemeCount() ) { + child = firstChild.getChildren().get(index); + } else { + index = index - firstChild.getNudMorphemeCount() + 1; + child = this.children.get(index); + } + } else if ( this.children.size() == 1 && !(this.children.get(0) instanceof ParseTree) && !(this.children.get(0) instanceof List) ) { + // TODO: I don't think this should ever be called + child = this.children.get(0); + } else { + child = this.children.get(index); + } + parameters.put(name, child.toAst()); + } + return new Ast(astNodeCreator.getName(), parameters); + } + } else { + AstTransformSubstitution defaultAction = new AstTransformSubstitution(0); + AstTransform action = this.astTransform != null ? this.astTransform : defaultAction; + if (this.children.size() == 0) return null; + if (action instanceof AstTransformSubstitution) { + AstTransformSubstitution astSubstitution = (AstTransformSubstitution) action; + return this.children.get(astSubstitution.getIndex()).toAst(); + } else if (action instanceof AstTransformNodeCreator) { + AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) action; + LinkedHashMap evaluatedParameters = new LinkedHashMap(); + for ( Map.Entry baseParameter : astNodeCreator.getParameters().entrySet() ) { + String name = baseParameter.getKey(); + int index2 = baseParameter.getValue().intValue(); + evaluatedParameters.put(name, this.children.get(index2).toAst()); + } + return new Ast(astNodeCreator.getName(), evaluatedParameters); + } + } + return null; + } + public String toString() { + ArrayList children = new ArrayList(); + for (ParseTreeNode child : this.children) { + children.add(child.toString()); + } + return "(" + this.nonterminal.getString() + ": " + Utility.join(children, ", ") + ")"; + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + if (this.children.size() == 0) { + return "(" + this.nonterminal.toString() + ": )"; + } + String spaces = Utility.getIndentString(indent); + ArrayList children = new ArrayList(); + for ( ParseTreeNode node : this.children ) { + String sub = node.toPrettyString(indent + 2).trim(); + children.add(spaces + " " + sub); + } + return spaces + "(" + this.nonterminal.toString() + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; + } +} diff --git a/dot/ParseTreeNode.java b/dot/ParseTreeNode.java new file mode 100644 index 0000000..9d6eb97 --- /dev/null +++ b/dot/ParseTreeNode.java @@ -0,0 +1,6 @@ +public interface ParseTreeNode { + public AstNode toAst(); + public String toString(); + public String toPrettyString(); + public String toPrettyString(int indent); +} diff --git a/dot/Parser.java b/dot/Parser.java new file mode 100644 index 0000000..8746412 --- /dev/null +++ b/dot/Parser.java @@ -0,0 +1,4 @@ +interface Parser { + ParseTree parse(TokenStream tokens) throws SyntaxError; + TerminalMap getTerminalMap(); +} diff --git a/dot/ParserMain.java b/dot/ParserMain.java new file mode 100644 index 0000000..3f3c231 --- /dev/null +++ b/dot/ParserMain.java @@ -0,0 +1,50 @@ +import org.json.*; +import java.io.*; +class ParserMain { + private static Parser getParser(String name) throws Exception { + if (name.equals("dot")) { + return new DotParser(); + } + throw new Exception("Invalid grammar name: " + name); + } + public static void main(String args[]) { + final String grammars = "dot"; + if ( args.length < 2 ) { + System.out.println("Usage: ParserMain <" + grammars + "> "); + System.exit(-1); + } + final String grammar = args[0].toLowerCase(); + try { + Parser parser = getParser(grammar); + TerminalMap terminals = parser.getTerminalMap(); + TokenStream tokens = new TokenStream(terminals); + String contents = Utility.readStdin(); + JSONArray arr = new JSONArray(contents); + for ( int i = 0; i < arr.length(); i++ ) { + JSONObject token = arr.getJSONObject(i); + tokens.add(new Terminal( + terminals.get(token.getString("terminal")), + token.getString("terminal"), + token.getString("source_string"), + token.getString("resource"), + token.getInt("line"), + token.getInt("col") + )); + } + ParseTreeNode parsetree = parser.parse(tokens); + if ( args.length > 1 && args[1].equals("ast") ) { + AstNode ast = parsetree.toAst(); + if ( ast != null ) { + System.out.println(ast.toPrettyString()); + } else { + System.out.println("None"); + } + } else { + System.out.println(parsetree.toPrettyString()); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + System.exit(-1); + } + } +} diff --git a/dot/SyntaxError.java b/dot/SyntaxError.java new file mode 100644 index 0000000..9ea950e --- /dev/null +++ b/dot/SyntaxError.java @@ -0,0 +1,5 @@ +class SyntaxError extends Exception { + SyntaxError(String message) { + super(message); + } +} diff --git a/dot/TODO b/dot/TODO new file mode 100644 index 0000000..39e3d43 --- /dev/null +++ b/dot/TODO @@ -0,0 +1,40 @@ +Lexer +----- + +1) There are 3 hint tokens that need to be emitted properly: + 0) value_assign_hint - comes before any sequence that looks like: identifier + assign + identifier + 1) edge_stmt_hint - a statement that contains an edge_op + 2) node_stmt_hint - statement that does NOT contain edge_op and starts with: node_id + +2) Lexer Notes: + 0) 'identifier' is: + a) Any string of alphabetic ([a-zA-Z\200-\377]) characters, underscores ('_') or digits ([0-9]), not beginning with a digit + i) [a-zA-Z\\200-\\377_]([0-9a-zA-Z\\200-\\377_])* + b) a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? ) + i) [-]?(\\.[0-9]+|[0-9]+(.[0-9]*)?) + c) any double-quoted string ("...") possibly containing escaped quotes (\") + i) \"(\\\"|[^\"])*\" + d) an HTML string (<...>) + i) <[^>]+> + +3) Algorithm: + 0) Cache starts out empty + 1) Collect tokens in a cache until one of the following conditions happens: + a) [\n\r]+ + i) if not within square brackets, goto stmt_end. + b) {[\r\n]* + i) output tokens in cache and clear cache. + c) }[\r\n]+, or EOF + i) if there are tokens in the cache, goto stmt_end. + d) \\[\r\n] + i) return + stmt_end) + i) if cache = ['identifier' + 'assign' + 'identifier'], hint = value_assign_hint + ii) if cache contains edgeop, hint = edge_stmt_hint + iii) if cache[0] = 'identifier' and cache does not contain edgeop, hint = node_stmt_hint + iv) if cache[-1] != 'semi', semi = 'semi' + end) + i) rval = [hint] + cache + [semi] + ii) cache = list() + iii) return rval + diff --git a/dot/Terminal.java b/dot/Terminal.java new file mode 100644 index 0000000..ab54dab --- /dev/null +++ b/dot/Terminal.java @@ -0,0 +1,51 @@ +import java.util.Formatter; +import java.util.Locale; +class Terminal implements AstNode, ParseTreeNode +{ + private int id; + private String terminal_str; + private String base64_source_string; + private String resource; + private int line; + private int col; + Terminal(int id, String terminal_str, String base64_source_string, String resource, int line, int col) { + this.id = id; + this.terminal_str = terminal_str; + this.base64_source_string = base64_source_string; + this.resource = resource; + this.line = line; + this.col = col; + } + public int getId() { + return this.id; + } + public String getTerminalStr() { + return this.terminal_str; + } + public String getBase64SourceString() { + return this.base64_source_string; + } + public String getResource() { + return this.resource; + } + public int getLine() { + return this.line; + } + public int getColumn() { + return this.col; + } + public String toString() { + StringBuilder sb = new StringBuilder(); + Formatter formatter = new Formatter(sb, Locale.US); + formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), this.getBase64SourceString()); + return formatter.toString(); + } + public String toPrettyString() { + return toPrettyString(0); + } + public String toPrettyString(int indent) { + String spaces = Utility.getIndentString(indent); + return spaces + this.getTerminalStr(); + } + public AstNode toAst() { return this; } +} diff --git a/dot/TerminalMap.java b/dot/TerminalMap.java new file mode 100644 index 0000000..f198d39 --- /dev/null +++ b/dot/TerminalMap.java @@ -0,0 +1,6 @@ +interface TerminalMap { + int get(String string); + String get(int id); + boolean isValid(String string); + boolean isValid(int id); +} diff --git a/dot/TokenStream.java b/dot/TokenStream.java new file mode 100644 index 0000000..b50e557 --- /dev/null +++ b/dot/TokenStream.java @@ -0,0 +1,44 @@ +import java.util.ArrayList; +import java.util.Formatter; +import java.util.Locale; +class TokenStream extends ArrayList { + private int index; + private TerminalMap terminals; + TokenStream(TerminalMap terminals) { + this.terminals = terminals; + reset(); + } + public void reset() { + this.index = 0; + } + public Terminal advance() { + this.index += 1; + return this.current(); + } + public Terminal current() { + try { + return this.get(this.index); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + public Terminal expect(int expecting) throws SyntaxError { + Terminal current = current(); + if (current == null) { + throw new SyntaxError( "No more tokens. Expecting " + this.terminals.get(expecting) ); + } + if (current.getId() != expecting) { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); + throw new SyntaxError(formatter.toString()); + } + Terminal next = advance(); + if ( next != null && !this.terminals.isValid(next.getId()) ) { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + formatter.format("Invalid symbol ID: %d (%s)", next.getId(), next.getTerminalStr()); + throw new SyntaxError(formatter.toString()); + } + return current; + } +} diff --git a/dot/Utility.java b/dot/Utility.java new file mode 100644 index 0000000..60bbde1 --- /dev/null +++ b/dot/Utility.java @@ -0,0 +1,81 @@ +import java.util.Collection; +import java.util.Iterator; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.nio.*; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +class Utility { + public static String join(Collection s, String delimiter) { + StringBuilder builder = new StringBuilder(); + Iterator iter = s.iterator(); + while (iter.hasNext()) { + builder.append(iter.next()); + if (!iter.hasNext()) { + break; + } + builder.append(delimiter); + } + return builder.toString(); + } + public static String getIndentString(int spaces) { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < spaces; i++) { + sb.append(' '); + } + return sb.toString(); + } + public static String base64_encode(byte[] bytes) { + int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4; + int cycle = 0, b64_index = 0; + byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); + byte[] b64 = new byte[b64_len]; + byte[] buffer = new byte[3]; + Arrays.fill(buffer, (byte) -1); + for (byte b : bytes) { + int index = cycle % 3; + buffer[index] = b; + boolean last = (cycle == (bytes.length - 1)); + if ( index == 2 || last ) { + if ( last ) { + if ( buffer[1] == -1 ) buffer[1] = 0; + if ( buffer[2] == -1 ) buffer[2] = 0; + } + b64[b64_index++] = alphabet[buffer[0] >> 2]; + b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)]; + b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)]; + b64[b64_index++] = alphabet[buffer[2] & 0x3f]; + if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '='; + if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '='; + Arrays.fill(buffer, (byte) -1); + } + cycle++; + } + return new String(b64); + } + public static String readStdin() throws IOException { + InputStreamReader stream = new InputStreamReader(System.in, "utf-8"); + char buffer[] = new char[System.in.available()]; + try { + stream.read(buffer, 0, System.in.available()); + } finally { + stream.close(); + } + return new String(buffer); + } + public static String readFile(String path) throws IOException { + FileInputStream stream = new FileInputStream(new File(path)); + try { + FileChannel fc = stream.getChannel(); + MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + /* Instead of using default, pass in a decoder. */ + return Charset.defaultCharset().decode(bb).toString(); + } + finally { + stream.close(); + } + } +} diff --git a/dot/dot.zgr b/dot/dot.zgr new file mode 100644 index 0000000..1b6d88e --- /dev/null +++ b/dot/dot.zgr @@ -0,0 +1,28 @@ +{ + "ll1": { + "start": "graph", + "rules": [ + "graph := optional('strict') + graph_type + optional('identifier') + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' -> Graph(strict=$0, type=$1, name=$2, statements=$4)", + "graph_type := 'graph' | 'digraph'", + "stmt := node_stmt | edge_stmt | attr_stmt | subgraph", + "stmt := 'value_assign_hint' + 'identifier' + 'assign' + 'identifier' -> Assign(key=$1, value=$3)", + "attr_stmt := attr_type + list(attr) -> Attribute(type=$0, values=$1)", + "attr_type := 'graph' | 'node' | 'edge'", + "attr := 'lsquare' + list(attr_values, 'comma') + 'rsquare' -> $1", + "attr_values := 'identifier' + optional(attr_value_assign) -> AttributeValue(key=$0, value=$1)", + "attr_value_assign := 'assign' + 'identifier' -> $1", + "edge_stmt := 'edge_stmt_hint' + node_or_subgraph + mlist(edge_rhs, 1) + list(attr) -> Edg(node=$1, edges=$2, attributes=$3)", + "edge_rhs := edge_op + node_or_subgraph -> EdgeDeclaration( edge_type=$0, node=$1 )", + "node_or_subgraph := node_id | subgraph", + "edge_op := 'arrow' | 'dashdash'", + "node_stmt := 'node_stmt_hint' + node_id + list(attr) -> Node(id=$1, attributes=$2)", + "node_id := 'identifier' + optional(port) -> NodeId(name=$0, port=$1)", + "port := 'colon' + port_sub -> $1", + "port_sub := 'identifier' + optional(port_compass_pt) -> Port(name=$0, compass_point=$1)", + "port_compass_pt := 'colon' + 'identifier' -> $1", + "port_sub := 'colon' + 'identifier' -> Port(name=$1)", + "subgraph := optional(subgraph_name) + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' -> SubGraph(name=$0, statements=$2)", + "subgraph_name := 'subgraph' + optional('identifier') - > $1" + ] + } +} diff --git a/dot/hermes.log b/dot/hermes.log new file mode 100644 index 0000000..e69de29 diff --git a/test/CopyNumberQC.wdl b/test/CopyNumberQC.wdl new file mode 100644 index 0000000..2e47f2d --- /dev/null +++ b/test/CopyNumberQC.wdl @@ -0,0 +1,33 @@ +composite_task CopyNumberQC { + step MakeLaneList_Normal: (normal_rcl) = MakeLaneList( File("normal.bam"), sample_id ); + step MakeLaneList_Tumor: (tumor_rcl) = MakeLaneList( File("tumor.bam"), sample_id ); + step RegionCovPerLane_Normal: (normal_rcl) = RegionCovPerLane(File("normal.bam"), sample_id, region_list); + step RegionCovPerLane_Tumor: (tumor_rcl) = RegionCovPerLane(File("sample.bam"), sample_id, region_list); + step LaneBlackList: (lane_blacklist) = LaneBlackList() + step CopyNumberQC_${sample.id}: (analysis_file, str) = CopyNumberQCReport(tumor_rcl, normal_rcl, individual_name, tumor_lanelist, normal_lanelist, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist); +} + +step MakeLaneList(File input_bam, String sample_id) { + output: File("lanelist.txt"); + action: task("MakeLaneList", version=11); +} + +step RegionCovPerLane(File input_bam, String sample_id, String region_list) { + output: File(""); + action: task("RegionCovPerLane", version=16); +} + +step LaneBackList() { + output: File("LaneBlackList.txt"); + action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); +} + +step CopyNumberQcReport(File tumor_rcl, File normal_rcl, String individual_name, File tumor_lanelist, File normal_lanelist, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist) { + output: File("dir/analysis.txt"), "static string"; + action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); +} + +step CopyNumberQcReport(ListFile lanelist, ListFile rcl) { + output: File("dir/analysis.txt"), "static string"; + action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); +} diff --git a/test/CopyNumberQCAlt.wdl b/test/CopyNumberQCAlt.wdl new file mode 100644 index 0000000..498f879 --- /dev/null +++ b/test/CopyNumberQCAlt.wdl @@ -0,0 +1,29 @@ +composite_task CopyNumberQC { + step LaneBlackList: (lane_blacklist) = LaneBlackList(); + + for ( sample in samples ) { + step MakeLaneList: (sample.lanelist) = MakeLaneList(sample.bam, sample.id, sample.regions); + step RegionCovPerLane: (sample.rcl) = RegionCovPerLane(sample.bam, sample.id, sample.regions); + } + + step CopyNumberQc: CopyNumberQCReport(samples.lanelist, samples.rcl, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist); +} + +task MakeLaneList(File input_bam, String sample_id) { + output: File("lanelist_${sample_id}.txt"); + action: task("MakeLaneList", version=11); +} + +task RegionCovPerLane(File input_bam, String sample_id, String region_list) { + output: File("sample_${sample_id}.rcl"); + action: task("RegionCovPerLane", version=16); +} + +task LaneBackList() { + output: File("LaneBlackList.txt"); + action: task("LaneBlackList", version=6); +} + +task CopyNumberQcReport(ListFile lanelist, ListFile rcl, String individual_name, FileList region_list, FileList normals_db, File tumor_seg, File normal_seg, File lane_blacklist) { + action: task("CopyNumberQCReport", version=25); +} diff --git a/test/org/json/JSONArray.class b/test/org/json/JSONArray.class deleted file mode 100644 index 83e6c9969cb05b848d6436f3b238b1765f0e822e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9162 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 E18ksnod5s; diff --git a/test/org/json/JSONObject.class b/test/org/json/JSONObject.class deleted file mode 100644 index 0393352d40d455cdf8aa5094900778d208c22927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17385 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 S<|@O7Tmz6K?h{Q;_x}OfJSF%5 diff --git a/test/org/json/JSONString.class b/test/org/json/JSONString.class deleted file mode 100644 index 329f686758d463a599abfa28eaaca9bd9cbc1e45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156 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 B8wLOX From 84978778a52afd18b0a4db03db63b734a632c225 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sun, 5 Aug 2012 21:07:33 -0400 Subject: [PATCH 011/140] remove temp file --- dot/.Lexer.java.swp | Bin 16384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dot/.Lexer.java.swp diff --git a/dot/.Lexer.java.swp b/dot/.Lexer.java.swp deleted file mode 100644 index 19ed8d91d7b73352ba9f2d0c63af4a95e207aea1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI3TZ|i58OJB3X-aPitx!RVs?$lO9q)Q4dqE`ZW`n$!Bo^Ka_AXG?o7H%H?48Yc z#+n)LCA(?g+lML-2p)JsLgJ>rAjIVb^?{2DNIbv;f(KAhP@xELhzep~alNw%UH0^7DduGKudvW-yPitCO3#^+oU^(}E z*>!9Do&{v)3$nrU&A{KLb`+l9t-9x{essP-_h?{lTRYZq+DXf#3Zx1QqQK+Yd~gG7gJEzIoB$g5++&)y3jX@2ru_(f0UUr&fhjNq-Vfdf&VaWb(X?-Z z+h7A+0~6pJI1NsL6X3`1)wCaiAAm1|SHR2QC9n-vKmmLVOn|fC1K?@!?!%h)dvFK* z7Q6v|3ce0r0tN6SI0H_Df1E-Y@E!1Na0sg43YY~s@ImmKhcxZ;U>hufi{L5n)=B6F zUI!0@cOHb^;FsW4@FnmvxCwSZ1VV5fOoG4Q;^sy01o$j`%=~;#UG^MvJ`%hFTBm!a zRjnGtqq}6)zd=3zR~yEP6-6}gOxtfX9hVyV^)Lz?J2E~xvwqzgy_p;R^ybFla~VC8 zCG&o?Vg(`o)?<|h4ac+GeAQfCC@$uga)r&(YB4{znjx8K?Y>R6D)qo>ZVg~`ZT4z0 zw{mSDvjf^3++fui(Byo+(`YUTto?!$Mwi;Iyezy-X1I%cmN2+)nyrfK*d&as2yZ*S zQzZ?{@r)82@732gh!xbs3^~wbLEE*$knrh(MC}&b%V4uAY6Tt%b}U!;ytE%iv|;+K z$ZVpm$n^|;Lzfdm)FCAFTY*h68FwttriS<`Y@06i>d}^wK^1O+TS4=3P`nR|R%D}y zut*4XL)xb-pYn3X8qt;$nwau@{+dqJz{KuMV++8mv-Gvdah+)2tXLua@P{_3XZzKz z9@l9!yC2aIea@<(A+1QoxL7N4z(_4P9_>t-^Ig=82jkR8X9vl%aA(VPGfEF3lx$Oe znIR3c9{8SsgfJmzhV+rPHexJB#)SF}BQv58sg81o(||P48SW{uoAJTWKu#bN@~S4d zoQZ+(l17QoyEzz^>aihfYA$z70cJ?f5Ha$$S!8kZEWN$<)HW*edhe8RlhQ6$$c`1! zp1W#XmYGon{(sS)?{TlG*L@Uch!m+wko06o2-W4@*=ry zsEt*<6X7T*G%~_0v)3)YPr?-chJTcZFfy(R$y6p(yC&ZzDr9Dc7!_=E88TG%hRER| z=}ZfT;w_}+2iRFyVU(G|ITNtODR;@Zl++Qq_Za6`mL!HMoy|`yb$l>4$|604WCw>F zUOWf7l9Y>)tUd}ox_x0+%*YqLR{QMSmKDslYBg+5Hsm07)vQu}MpSsJbPy{R(rBJ% zp=gyA4NV+NGAY>}3L+CFWGxeNE?Es~@Y4qelWcU+YBp(=sVaLQOtPl8EYG8^*|3_% z6+F|SA^sgT7P0%8#f9Ab=JHbE`7D9Hs&wew#MvYpPgGL{&@ekkSx(+-w%BG%t%lrv zGt9%%ju=dPx8;41TW*#}x2wU#2}=76W@g~;h9tkduxHa|vJs6AwTb1&jYrAz zUBt$3gEv`>41Nt>122G0umFa@Bj9a};g8@=Ii5RgOzA6CAXOk$AXVW1SpgQ=i0DSe zIPzkF?m3Y$Ixe4DUklM!(@#2({SSk5kmI@@ERAiqoLDyHtJVl71%@c#tsc*n5@uF zHB{VXu#4ICu?-caMZv!6sB-o3*M+_oT6H=l?{zOZET$th$Z%QRyYa}MnUvSEV6t9*2PZ|<#KCmVr*=by-!}au(@HZkBxrhE_s>Z z!?JFa%Vqs={d!s7$PAbDWBiVhpI=y7&0onc6ypVOKV6;a|4T`(RLWmn8mRTD{;kg~ z7nTQWJbRqR7Z-B_^&B1>o2asXCux5>xngnolLOfq9qr%xe6DnjF_3|B89!<+z^(r67YA>Dx_|4Xg~j|p;(It-?*C`V UrRDj-q@vaO0Ol6vuL^Vj0=~w Date: Wed, 8 Aug 2012 08:30:19 -0400 Subject: [PATCH 012/140] test DOT parser --- dot/0.dot | 2 +- dot/DotParser.java | 920 +++++++++++---------- dot/Lexer.java | 288 ++++++- dot/Terminal.java | 2 +- dot/TokenStream.java | 2 +- dot/org/json/CDL.java | 279 +++++++ dot/org/json/Cookie.java | 169 ++++ dot/org/json/CookieList.java | 90 ++ dot/org/json/HTTP.java | 163 ++++ dot/org/json/HTTPTokener.java | 77 ++ dot/org/json/JSONArray.class | Bin 0 -> 9162 bytes dot/org/json/JSONArray.java | 906 ++++++++++++++++++++ dot/org/json/JSONException.class | Bin 0 -> 587 bytes dot/org/json/JSONException.java | 28 + dot/org/json/JSONML.java | 467 +++++++++++ dot/org/json/JSONObject$1.class | Bin 0 -> 199 bytes dot/org/json/JSONObject$Null.class | Bin 0 -> 656 bytes dot/org/json/JSONObject.class | Bin 0 -> 17385 bytes dot/org/json/JSONObject.java | 1593 ++++++++++++++++++++++++++++++++++++ dot/org/json/JSONString.class | Bin 0 -> 156 bytes dot/org/json/JSONString.java | 18 + dot/org/json/JSONStringer.java | 78 ++ dot/org/json/JSONTokener.class | Bin 0 -> 5033 bytes dot/org/json/JSONTokener.java | 446 ++++++++++ dot/org/json/JSONWriter.java | 327 ++++++++ dot/org/json/XML.java | 508 ++++++++++++ dot/org/json/XMLTokener.java | 365 +++++++++ dot/tokens | 126 +++ 28 files changed, 6384 insertions(+), 470 deletions(-) create mode 100755 dot/org/json/CDL.java create mode 100755 dot/org/json/Cookie.java create mode 100755 dot/org/json/CookieList.java create mode 100755 dot/org/json/HTTP.java create mode 100755 dot/org/json/HTTPTokener.java create mode 100644 dot/org/json/JSONArray.class create mode 100644 dot/org/json/JSONArray.java create mode 100644 dot/org/json/JSONException.class create mode 100755 dot/org/json/JSONException.java create mode 100755 dot/org/json/JSONML.java create mode 100644 dot/org/json/JSONObject$1.class create mode 100644 dot/org/json/JSONObject$Null.class create mode 100644 dot/org/json/JSONObject.class create mode 100755 dot/org/json/JSONObject.java create mode 100644 dot/org/json/JSONString.class create mode 100755 dot/org/json/JSONString.java create mode 100755 dot/org/json/JSONStringer.java create mode 100644 dot/org/json/JSONTokener.class create mode 100644 dot/org/json/JSONTokener.java create mode 100755 dot/org/json/JSONWriter.java create mode 100755 dot/org/json/XML.java create mode 100755 dot/org/json/XMLTokener.java create mode 100644 dot/tokens diff --git a/dot/0.dot b/dot/0.dot index c8f6877..3f2b189 100644 --- a/dot/0.dot +++ b/dot/0.dot @@ -1 +1 @@ -digraph G {"Hello"->World} +digraph G {Hello->World} diff --git a/dot/DotParser.java b/dot/DotParser.java index 0347416..041261b 100644 --- a/dot/DotParser.java +++ b/dot/DotParser.java @@ -7,59 +7,59 @@ private HashMap expressionParsers; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { 30, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27 }, - { -1, 51, -1, -1, 44, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 39, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 24, -1, -1, -1, -1, -1, -1, -1, 10, 24, -1, 43, -1, 26, 10, -1, 24, 9, -1, -1 }, - { -1, -1, 40, -1, -1, -1, 40, 40, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, 40, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1 }, - { -1, -1, 33, -1, -1, -1, 37, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1 }, - { 4, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1 }, - { 35, -1, -1, -1, -1, -1, -1, -1, 35, 35, -1, 35, 11, 35, 35, -1, 35, 35, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1 }, - { 28, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1 }, - { 22, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, - { 23, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, 50, -1, -1, -1, -1, -1 }, - { -1, -1, 12, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 47, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, 0, -1, -1, -1, 5, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1 }, - { -1, -1, 18, -1, -1, -1, 18, 18, -1, -1, -1, -1, -1, -1, -1, 46, -1, -1, 18, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, 17, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, 35, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 17, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, 41, 41, -1, -1, -1, -1, -1, -1 }, + { 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1 }, + { 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, 6, -1, 44, -1 }, + { -1, -1, 36, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, 50 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, 5, -1, -1, -1 }, + { -1, 31, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, 30, 30, -1, -1, -1, -1, -1, -1 }, + { -1, 33, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 45, 16, 45, -1, 16, 40, -1, -1, -1, -1, -1, -1, 16, -1, 21, -1, 32, -1, -1 }, + { 42, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, 42, -1, 42, -1 }, + { -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 51, -1, -1, 51, -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, -1, -1, -1, -1 }, + { -1, 38, -1, 38, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 28, 28, 28, -1, 28, 28, -1, -1, -1, 47, -1, -1, 28, -1, 28, -1, 28, -1, -1 }, + { 49, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1, 49, -1, 49, -1 }, + { -1, 24, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 }, + { -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId { - TERMINAL_GRAPH(0, "graph"), - TERMINAL_RSQUARE(1, "rsquare"), - TERMINAL_SEMI(2, "semi"), - TERMINAL_DIGRAPH(3, "digraph"), - TERMINAL_ASSIGN(4, "assign"), - TERMINAL_COMMA(5, "comma"), - TERMINAL_ARROW(6, "arrow"), - TERMINAL_LSQUARE(7, "lsquare"), - TERMINAL_LBRACE(8, "lbrace"), - TERMINAL_EDGE(9, "edge"), - TERMINAL_IDENTIFIER(10, "identifier"), - TERMINAL_VALUE_ASSIGN_HINT(11, "value_assign_hint"), - TERMINAL_RBRACE(12, "rbrace"), - TERMINAL_EDGE_STMT_HINT(13, "edge_stmt_hint"), - TERMINAL_SUBGRAPH(14, "subgraph"), - TERMINAL_COLON(15, "colon"), - TERMINAL_NODE(16, "node"), - TERMINAL_NODE_STMT_HINT(17, "node_stmt_hint"), - TERMINAL_DASHDASH(18, "dashdash"), - TERMINAL_STRICT(19, "strict"); + TERMINAL_DASHDASH(0, "dashdash"), + TERMINAL_LBRACE(1, "lbrace"), + TERMINAL_NODE(2, "node"), + TERMINAL_SUBGRAPH(3, "subgraph"), + TERMINAL_COLON(4, "colon"), + TERMINAL_EDGE(5, "edge"), + TERMINAL_NODE_STMT_HINT(6, "node_stmt_hint"), + TERMINAL_STRICT(7, "strict"), + TERMINAL_RSQUARE(8, "rsquare"), + TERMINAL_IDENTIFIER(9, "identifier"), + TERMINAL_RBRACE(10, "rbrace"), + TERMINAL_LSQUARE(11, "lsquare"), + TERMINAL_DIGRAPH(12, "digraph"), + TERMINAL_GRAPH(13, "graph"), + TERMINAL_COMMA(14, "comma"), + TERMINAL_EDGE_STMT_HINT(15, "edge_stmt_hint"), + TERMINAL_SEMI(16, "semi"), + TERMINAL_VALUE_ASSIGN_HINT(17, "value_assign_hint"), + TERMINAL_ARROW(18, "arrow"), + TERMINAL_ASSIGN(19, "assign"); private final int id; private final String string; TerminalId(int id, String string) { @@ -113,68 +113,119 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (20 <= terminal && terminal <= 50); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse_graph_type() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(20, "_gen0")); + ParseTree tree = new ParseTree( new NonTerminal(20, "graph_type")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_graph_type(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); - if ( current != null ) { - if (current.getId() == 0 || current.getId() == 3) { - return tree; - } - } if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 35) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + tree.add(next); return tree; } - if (rule == 27) { + else if (rule == 48) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); + next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); tree.add(next); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_port_sub() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(21, "_gen6")); + ParseTree tree = new ParseTree( new NonTerminal(21, "port_sub")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_port_sub(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); - if ( current != null ) { - if (current.getId() == 5 || current.getId() == 1) { - return tree; - } - } if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 12) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("compass_point", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen10(); + tree.add( subtree); return tree; } - if (rule == 44) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_value_assign(); + else if (rule == 17) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr_values() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(22, "attr_values")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_values(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 22) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 1); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen6(); tree.add( subtree); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "_gen5")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen5")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen5(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 1) { + if (current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 48) { + if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); @@ -187,94 +238,52 @@ private ParseTree parse__gen5() throws SyntaxError { } return tree; } - private ParseTree parse_stmt() throws SyntaxError { + private ParseTree parse_edge_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "stmt")); + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "edge_stmt")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } if (rule == 9) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_node_stmt(); - tree.add( subtree); - return tree; - } - else if (rule == 10) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph(); + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("node", 1); + parameters.put("attributes", 3); + parameters.put("edges", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Edg", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); + tree.add(next); + subtree = this.parse_node_or_subgraph(); tree.add( subtree); - return tree; - } - else if (rule == 24) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_stmt(); + subtree = this.parse__gen7(); tree.add( subtree); - return tree; - } - else if (rule == 26) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_stmt(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } - else if (rule == 43) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 3); - parameters.put("key", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen10() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen10")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 7 || current.getId() == 18 || current.getId() == 6 || current.getId() == 2) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 49) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_port_compass_pt(); - tree.add( subtree); - return tree; - } - return tree; - } private ParseTree parse_port_compass_pt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(25, "port_compass_pt")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_port_compass_pt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 7) { + if (rule == 3) { tree.setAstTransformation(new AstTransformSubstitution(1)); next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); @@ -287,57 +296,65 @@ private ParseTree parse_port_compass_pt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse_graph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "_gen8")); - tree.setList("mlist"); - if ( current != null ) { - if (current.getId() == 7 || current.getId() == 2) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(26, "graph")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_graph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 37) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_rhs(); + if (rule == 41) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("strict", 0); + parameters.put("type", 1); + parameters.put("name", 2); + parameters.put("statements", 4); + tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); + subtree = this.parse__gen0(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse_graph_type(); + tree.add( subtree); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr_type() throws SyntaxError { + private ParseTree parse_edge_rhs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "attr_type")); + ParseTree tree = new ParseTree( new NonTerminal(27, "edge_rhs")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_rhs(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 1) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); - tree.add(next); - return tree; - } - else if (rule == 4) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); - tree.add(next); - return tree; - } - else if (rule == 20) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); - tree.add(next); + if (rule == 14) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("node", 1); + parameters.put("edge_type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); + subtree = this.parse_edge_op(); + tree.add( subtree); + subtree = this.parse_node_or_subgraph(); + tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -345,49 +362,61 @@ else if (rule == 20) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen2")); - tree.setList("tlist"); + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen8")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen8(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList("mlist"); if ( current != null ) { - if (current.getId() == 12) { + if (current.getId() == 11 || current.getId() == 16) { return tree; } } if (current == null) { return tree; } - if (rule == 35) { + if (rule == 44) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_stmt(); + subtree = this.parse_edge_rhs(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_subgraph_name() throws SyntaxError { + private ParseTree parse_attr_type() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "subgraph_name")); + ParseTree tree = new ParseTree( new NonTerminal(29, "attr_type")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_type(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); + tree.add(next); + return tree; + } + else if (rule == 27) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + tree.add(next); + return tree; + } + else if (rule == 36) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); tree.add(next); - subtree = this.parse__gen1(); - tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -401,11 +430,13 @@ private ParseTree parse_node_id() throws SyntaxError { ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(30, "node_id")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_id(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 16) { + if (rule == 34) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("name", 0); parameters.put("port", 1); @@ -421,52 +452,51 @@ private ParseTree parse_node_id() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen6")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen6(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList(null); if ( current != null ) { - if (current.getId() == 1) { + if (current.getId() == 14 || current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 25) { + if (rule == 50) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_values(); - tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse_attr_value_assign(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_node_stmt() throws SyntaxError { + private ParseTree parse_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "node_stmt")); + ParseTree tree = new ParseTree( new NonTerminal(32, "attr")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 32) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 2); - parameters.put("id", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); + if (rule == 43) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); tree.add(next); - subtree = this.parse_node_id(); - tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen4(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -474,24 +504,23 @@ private ParseTree parse_node_stmt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr_stmt() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "attr_stmt")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(33, "_gen7")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen7(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList("mlist"); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 28) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("values", 1); - parameters.put("type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); - subtree = this.parse_attr_type(); + if (rule == 1) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_edge_rhs(); tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } @@ -500,91 +529,79 @@ private ParseTree parse_attr_stmt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_graph_type() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "graph_type")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + ParseTree tree = new ParseTree( new NonTerminal(34, "_gen3")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen3(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 16) { + return tree; + } } - if (rule == 22) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); - tree.add(next); + if (current == null) { return tree; } - else if (rule == 36) { + if (rule == 15) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); - tree.add(next); + subtree = this.parse_attr(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_subgraph() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "subgraph")); + ParseTree tree = new ParseTree( new NonTerminal(35, "_gen1")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen1(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); + if ( current != null ) { + if (current.getId() == 1) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 13) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("statements", 2); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); - subtree = this.parse__gen11(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + if (rule == 11) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_graph() throws SyntaxError { + private ParseTree parse_edge_op() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "graph")); + ParseTree tree = new ParseTree( new NonTerminal(36, "edge_op")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_op(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 23) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("strict", 0); - parameters.put("type", 1); - parameters.put("name", 2); - parameters.put("statements", 4); - tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); - subtree = this.parse__gen0(); - tree.add( subtree); - subtree = this.parse_graph_type(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + if (rule == 2) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + return tree; + } + else if (rule == 26) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); tree.add(next); return tree; } @@ -593,127 +610,161 @@ private ParseTree parse_graph() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "_gen11")); + ParseTree tree = new ParseTree( new NonTerminal(37, "_gen0")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen0(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if ( current != null ) { - if (current.getId() == 8) { + if (current.getId() == 13 || current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 50) { + if (rule == 18) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph_name(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); + tree.add(next); return tree; } return tree; } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_subgraph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen3")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 2) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(38, "subgraph")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_subgraph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 6) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr(); + if (rule == 33) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("statements", 2); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); + subtree = this.parse__gen11(); tree.add( subtree); - subtree = this.parse__gen3(); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse_edge_op() throws SyntaxError { + private ParseTree parse_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "edge_op")); + ParseTree tree = new ParseTree( new NonTerminal(39, "stmt")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 8) { + if (rule == 16) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); - tree.add(next); + subtree = this.parse_attr_stmt(); + tree.add( subtree); return tree; } - else if (rule == 29) { + else if (rule == 21) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); + subtree = this.parse_edge_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 32) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 3); + parameters.put("key", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } + else if (rule == 40) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_node_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 45) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_subgraph(); + tree.add( subtree); + return tree; + } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_edge_stmt() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "edge_stmt")); + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen9")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen9(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); + if ( current != null ) { + if (current.getId() == 0 || current.getId() == 16 || current.getId() == 18 || current.getId() == 11) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 38) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("attributes", 3); - parameters.put("edges", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Edg", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); - tree.add(next); - subtree = this.parse_node_or_subgraph(); - tree.add( subtree); - subtree = this.parse__gen7(); - tree.add( subtree); - subtree = this.parse__gen3(); + if (rule == 7) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_port(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse_subgraph_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "_gen7")); - tree.setList("mlist"); + ParseTree tree = new ParseTree( new NonTerminal(41, "subgraph_name")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_subgraph_name(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 31) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_rhs(); - tree.add( subtree); - subtree = this.parse__gen8(); + if (rule == 4) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } @@ -722,24 +773,27 @@ private ParseTree parse__gen7() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr() throws SyntaxError { + private ParseTree parse_attr_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "attr")); + ParseTree tree = new ParseTree( new NonTerminal(42, "attr_stmt")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 3) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); - tree.add(next); - subtree = this.parse__gen4(); + if (rule == 51) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("values", 1); + parameters.put("type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); + subtree = this.parse_attr_type(); + tree.add( subtree); + subtree = this.parse__gen3(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); - tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -747,46 +801,25 @@ private ParseTree parse_attr() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen1() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen1")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 8) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 42) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - return tree; - } private ParseTree parse_node_or_subgraph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "node_or_subgraph")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "node_or_subgraph")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_or_subgraph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 0) { + if (rule == 23) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_node_id(); tree.add( subtree); return tree; } - else if (rule == 5) { + else if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_subgraph(); tree.add( subtree); @@ -797,107 +830,103 @@ else if (rule == 5) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_port() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "port")); - tree.setList(null); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "_gen2")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen2(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList("tlist"); + if ( current != null ) { + if (current.getId() == 10) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 15) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + if (rule == 28) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_stmt(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); tree.add(next); - subtree = this.parse_port_sub(); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_edge_rhs() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "edge_rhs")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "_gen10")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen10(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); + if ( current != null ) { + if (current.getId() == 0 || current.getId() == 16 || current.getId() == 18 || current.getId() == 11) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 19) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("edge_type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); - subtree = this.parse_edge_op(); - tree.add( subtree); - subtree = this.parse_node_or_subgraph(); + if (rule == 13) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_port_compass_pt(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen11() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "_gen9")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "_gen11")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen11(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if ( current != null ) { - if (current.getId() == 7 || current.getId() == 18 || current.getId() == 6 || current.getId() == 2) { + if (current.getId() == 1) { return tree; } } if (current == null) { return tree; } - if (rule == 46) { + if (rule == 29) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_port(); + subtree = this.parse_subgraph_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_port_sub() throws SyntaxError { + private ParseTree parse_attr_value_assign() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "port_sub")); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "attr_value_assign")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_value_assign(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 17) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + if (rule == 25) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); tree.add(next); - return tree; - } - else if (rule == 45) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("compass_point", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); - subtree = this.parse__gen10(); - tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -905,22 +934,24 @@ else if (rule == 45) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr_value_assign() throws SyntaxError { + private ParseTree parse_port() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "attr_value_assign")); + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "port")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_port(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 14) { + if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); + subtree = this.parse_port_sub(); + tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -928,24 +959,28 @@ private ParseTree parse_attr_value_assign() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr_values() throws SyntaxError { + private ParseTree parse_node_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[30][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "attr_values")); + int rule = current != null ? this.table[29][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "node_stmt")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 21) { + if (rule == 46) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 1); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + parameters.put("attributes", 2); + parameters.put("id", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); tree.add(next); - subtree = this.parse__gen6(); + subtree = this.parse_node_id(); + tree.add( subtree); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } @@ -954,4 +989,31 @@ private ParseTree parse_attr_values() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } + private ParseTree parse__gen4() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[30][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen4")); + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen4(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 8) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr_values(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } } diff --git a/dot/Lexer.java b/dot/Lexer.java index 40297bb..f57ab2b 100644 --- a/dot/Lexer.java +++ b/dot/Lexer.java @@ -1,5 +1,7 @@ import java.util.regex.*; +import java.util.concurrent.Callable; import java.util.ArrayList; +import java.util.List; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -15,12 +17,14 @@ private String contents; private int line; private int col; + private int nchars; SourceCode(String source, String resource) { this.contents = source; this.resource = resource; this.line = 1; this.col = 1; + this.nchars = 0; } SourceCode(File source) throws IOException { @@ -43,6 +47,10 @@ this.col = 1; } + public int getCharactersProcessed() { + return this.nchars; + } + public void advance(int amount) { String str = this.contents.substring(0, amount); for ( byte b : str.getBytes() ) { @@ -54,6 +62,7 @@ public void advance(int amount) { } } this.contents = this.contents.substring(amount); + this.nchars += amount; } public String getString() { @@ -74,64 +83,258 @@ public int getCol() { } class LexerMatch { - private Terminal terminal; - LexerMatch() { this.terminal = null; } - LexerMatch(Terminal terminal) { this.terminal = terminal; } - public Terminal getTerminal() { return this.terminal; } + private List terminals; + LexerMatch() { this.terminals = null; } + LexerMatch(List terminals) { this.terminals = terminals; } + public List getTerminals() { return this.terminals; } + public void append(Terminal terminal) {this.terminals.add(terminal);} +} + +abstract class TokenMatchCallback implements Callable { + protected Terminal terminal; + protected LexerState state; + protected void setContext(Terminal terminal, LexerState state) { + this.terminal = terminal; + this.state = state; + } + public abstract LexerMatch call(); } class TokenLexer { private Pattern regex; private DotParser.TerminalId terminal; + private TokenMatchCallback handler; TokenLexer(Pattern regex, DotParser.TerminalId terminal) { + this(regex, terminal, null); + } + + TokenLexer(Pattern regex, DotParser.TerminalId terminal, TokenMatchCallback handler) { this.regex = regex; this.terminal = terminal; + this.handler = handler; } - LexerMatch match(SourceCode source) { + LexerMatch match(SourceCode source, LexerState state) { Matcher m = this.regex.matcher(source.getString()); - System.out.println("["); - //System.out.println("[\n code='"+source.getString().trim()+"'"); - System.out.println(" pattern="+m.pattern()); LexerMatch rval = null; + + String code = source.getString().length() > 20 ? source.getString().substring(0, 20) : source.getString(); + if ( m.find() ) { - System.out.println(" match"); String sourceString = m.group(); + Terminal terminal = null; - if (this.terminal != null) - rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol())); - else - rval = new LexerMatch(); + if ( this.terminal != null ) { + terminal = new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol()); + } source.advance(sourceString.length()); + + if ( this.handler != null ) { + this.handler.setContext(terminal, state); + return this.handler.call(); + } else { + ArrayList list = new ArrayList(); + if ( terminal != null ) + list.add(terminal); + return new LexerMatch(list); + } } - System.out.println("]"); return rval; } } +class LexerState { + private ArrayList cache; + private int square_bracket; + LexerState() { + this.cache = new ArrayList(); + this.square_bracket = 0; + } + public void add(Terminal terminal) { + this.cache.add(terminal); + } + public List getCache() { + return this.cache; + } + public void clearCache() { + this.cache = new ArrayList(); + } + public void square_inc() { + this.square_bracket++; + } + public void square_dec() { + this.square_bracket--; + } + public int square_level() { + return this.square_bracket; + } + + private boolean cache_contains(DotParser.TerminalId input) { + if ( this.cache.size() > 0 ) { + for ( Terminal t : this.cache ) { + if ( t.getId() == input.id() ) { + return true; + } + } + } + return false; + } + + private boolean cache_contains_edgeop() { + return cache_contains(DotParser.TerminalId.TERMINAL_DASHDASH) || cache_contains(DotParser.TerminalId.TERMINAL_ARROW); + } + + public LexerMatch stmt_end() { + /* + stmt_end) + i) if cache = ['identifier' + 'assign' + 'identifier'], hint = value_assign_hint + ii) if cache contains edgeop, hint = edge_stmt_hint + iii) if cache[0] = 'identifier' and cache does not contain edgeop, hint = node_stmt_hint + iv) if cache[-1] != 'semi', semi = 'semi' + */ + + ArrayList tokens = new ArrayList(); + Terminal hint = null, semi = null; + + if ( this.cache.size() == 0 ) { + return null; + } + + if ( this.cache.size() >= 3 && + this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() && + this.cache.get(1).getId() == DotParser.TerminalId.TERMINAL_ASSIGN.id() && + this.cache.get(2).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { + DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_VALUE_ASSIGN_HINT; + hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); + } + else if ( cache_contains_edgeop() ) { + DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_EDGE_STMT_HINT; + hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); + } + else if ( this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { + DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_NODE_STMT_HINT; + hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); + } + + if ( this.cache.get(this.cache.size()-1).getId() != DotParser.TerminalId.TERMINAL_SEMI.id() ) { + DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_SEMI; + semi = new Terminal( t.id(), t.string(), "", "Auto-inserted semi-colon", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); + } + + if ( hint != null ) { + tokens.add(hint); + } + + tokens.addAll(this.cache); + + if ( semi != null ) { + tokens.add(semi); + } + + this.clearCache(); + return new LexerMatch(tokens); + } +} + public class Lexer { + private static class BackslashNewlineCallback extends TokenMatchCallback { + /* called on \\[\r\n] */ + public LexerMatch call() { + return null; + } + } + private static class RightBraceOrEOFCallback extends TokenMatchCallback { + /* called on }[\r\n]* or EOF */ + public LexerMatch call() { + if ( this.state.getCache().size() > 0 ) { + LexerMatch match = this.state.stmt_end(); + match.append(this.terminal); + return match; + } else { + this.state.add(this.terminal); + LexerMatch match = new LexerMatch(this.state.getCache()); + this.state.clearCache(); + return match; + } + } + } + private static class LeftBraceCallback extends TokenMatchCallback { + /* called on {[\r\n]* */ + public LexerMatch call() { + if ( this.state.getCache().size() > 0 ) { + this.state.add(this.terminal); + LexerMatch match = new LexerMatch(this.state.getCache()); + this.state.clearCache(); + return match; + } + // output tokens in cache and clear cache. + return null; + } + } + private static class NewLineCallback extends TokenMatchCallback { + /* called on [\r\n]+ */ + public LexerMatch call() { + if ( this.state.square_level() == 0 ) { + return this.state.stmt_end(); + } + // if not within square brackets, goto stmt_end. + return null; + } + } + private static class LeftSquareBracketCallback extends TokenMatchCallback { + /* called on \\[ */ + public LexerMatch call() { + if ( this.terminal != null ) { + this.state.square_inc(); + this.state.add(this.terminal); + } + return null; + } + } + private static class RightSquareBracketCallback extends TokenMatchCallback { + /* called on \\] */ + public LexerMatch call() { + if ( this.terminal != null ) { + this.state.square_dec(); + this.state.add(this.terminal); + } + return null; + } + } + private static class TokenCallback extends TokenMatchCallback { + /* Called on all other tokens */ + public LexerMatch call() { + if ( this.terminal != null ) { + this.state.add(this.terminal); + } + return null; + } + } public static void main(String[] args) { ArrayList regex = new ArrayList(); - regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_DIGRAPH) ); - regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_GRAPH) ); - regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_SUBGRAPH) ); - regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_STRICT) ); - regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_EDGE) ); - regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_NODE) ); - regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI) ); - regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE) ); - regex.add( new TokenLexer(Pattern.compile("^\\{"), DotParser.TerminalId.TERMINAL_LBRACE) ); - regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE) ); - regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE) ); - regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH) ); - regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW) ); - regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA) ); - regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON) ); - regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN) ); - regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\")|[-]?(\\.[0-9]+|[0-9]+(.[0-9]*)?)"), DotParser.TerminalId.TERMINAL_IDENTIFIER) ); - regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); + TokenCallback cb = new TokenCallback(); + regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_DIGRAPH, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_GRAPH, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_SUBGRAPH, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_STRICT, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_EDGE, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_NODE, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\}[\r\n]*"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceOrEOFCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\{[\r\n]*"), DotParser.TerminalId.TERMINAL_LBRACE, new LeftBraceCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE, new LeftSquareBracketCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE, new RightSquareBracketCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\\\[\r\n]"), DotParser.TerminalId.TERMINAL_ASSIGN, new BackslashNewlineCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\"|[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?))"), DotParser.TerminalId.TERMINAL_IDENTIFIER, new TokenCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^[\r\n]+"), null, new NewLineCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\s+"), null, new TokenCallback()) ); if ( args.length < 1 ) { System.err.println("Usage: Lexer "); @@ -140,25 +343,34 @@ public static void main(String[] args) { try { SourceCode code = new SourceCode(new File(args[0])); - ArrayList terminal_strings = new ArrayList(); + LexerState state = new LexerState(); + ArrayList terminals = new ArrayList(); + int consumed; boolean progress = true; while (progress) { progress = false; + consumed = code.getCharactersProcessed(); for ( TokenLexer lexer : regex ) { - LexerMatch match = lexer.match(code); + LexerMatch match = lexer.match(code, state); + if (match != null) { + terminals.addAll(match.getTerminals()); + } + + if ( consumed < code.getCharactersProcessed() ) { progress = true; - if (match.getTerminal() != null) { - terminal_strings.add( " " + match.getTerminal() ); - } break; } } } + ArrayList strs = new ArrayList(); + for (Terminal t : terminals) { + strs.add(" " + t.toString()); + } System.out.println("["); - System.out.println( Utility.join(terminal_strings, ",\n") ); + System.out.println( Utility.join(strs, ",\n") ); System.out.println("]"); System.out.flush(); } catch (IOException e) { diff --git a/dot/Terminal.java b/dot/Terminal.java index ab54dab..acc252b 100644 --- a/dot/Terminal.java +++ b/dot/Terminal.java @@ -45,7 +45,7 @@ public String toPrettyString() { } public String toPrettyString(int indent) { String spaces = Utility.getIndentString(indent); - return spaces + this.getTerminalStr(); + return spaces + this.toString(); } public AstNode toAst() { return this; } } diff --git a/dot/TokenStream.java b/dot/TokenStream.java index b50e557..60dd51e 100644 --- a/dot/TokenStream.java +++ b/dot/TokenStream.java @@ -30,7 +30,7 @@ public Terminal expect(int expecting) throws SyntaxError { if (current.getId() != expecting) { Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); + formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current : ""); throw new SyntaxError(formatter.toString()); } Terminal next = advance(); diff --git a/dot/org/json/CDL.java b/dot/org/json/CDL.java new file mode 100755 index 0000000..fd5d476 --- /dev/null +++ b/dot/org/json/CDL.java @@ -0,0 +1,279 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * This provides static methods to convert comma delimited text into a + * JSONArray, and to covert a JSONArray into comma delimited text. Comma + * delimited text is a very popular format for data interchange. It is + * understood by most database, spreadsheet, and organizer programs. + *

+ * Each row of text represents a row in a table or a data record. Each row + * ends with a NEWLINE character. Each row contains one or more values. + * Values are separated by commas. A value can contain any character except + * for comma, unless is is wrapped in single quotes or double quotes. + *

+ * The first row usually contains the names of the columns. + *

+ * A comma delimited list can be converted into a JSONArray of JSONObjects. + * The names for the elements in the JSONObjects can be taken from the names + * in the first row. + * @author JSON.org + * @version 2010-12-24 + */ +public class CDL { + + /** + * Get the next value. The value can be wrapped in quotes. The value can + * be empty. + * @param x A JSONTokener of the source text. + * @return The value string, or null if empty. + * @throws JSONException if the quoted string is badly formed. + */ + private static String getValue(JSONTokener x) throws JSONException { + char c; + char q; + StringBuffer sb; + do { + c = x.next(); + } while (c == ' ' || c == '\t'); + switch (c) { + case 0: + return null; + case '"': + case '\'': + q = c; + sb = new StringBuffer(); + for (;;) { + c = x.next(); + if (c == q) { + break; + } + if (c == 0 || c == '\n' || c == '\r') { + throw x.syntaxError("Missing close quote '" + q + "'."); + } + sb.append(c); + } + return sb.toString(); + case ',': + x.back(); + return ""; + default: + x.back(); + return x.nextTo(','); + } + } + + /** + * Produce a JSONArray of strings from a row of comma delimited values. + * @param x A JSONTokener of the source text. + * @return A JSONArray of strings. + * @throws JSONException + */ + public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { + JSONArray ja = new JSONArray(); + for (;;) { + String value = getValue(x); + char c = x.next(); + if (value == null || + (ja.length() == 0 && value.length() == 0 && c != ',')) { + return null; + } + ja.put(value); + for (;;) { + if (c == ',') { + break; + } + if (c != ' ') { + if (c == '\n' || c == '\r' || c == 0) { + return ja; + } + throw x.syntaxError("Bad character '" + c + "' (" + + (int)c + ")."); + } + c = x.next(); + } + } + } + + /** + * Produce a JSONObject from a row of comma delimited text, using a + * parallel JSONArray of strings to provides the names of the elements. + * @param names A JSONArray of names. This is commonly obtained from the + * first row of a comma delimited text file using the rowToJSONArray + * method. + * @param x A JSONTokener of the source text. + * @return A JSONObject combining the names and values. + * @throws JSONException + */ + public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) + throws JSONException { + JSONArray ja = rowToJSONArray(x); + return ja != null ? ja.toJSONObject(names) : null; + } + + /** + * Produce a comma delimited text row from a JSONArray. Values containing + * the comma character will be quoted. Troublesome characters may be + * removed. + * @param ja A JSONArray of strings. + * @return A string ending in NEWLINE. + */ + public static String rowToString(JSONArray ja) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < ja.length(); i += 1) { + if (i > 0) { + sb.append(','); + } + Object object = ja.opt(i); + if (object != null) { + String string = object.toString(); + if (string.length() > 0 && (string.indexOf(',') >= 0 || + string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || + string.indexOf(0) >= 0 || string.charAt(0) == '"')) { + sb.append('"'); + int length = string.length(); + for (int j = 0; j < length; j += 1) { + char c = string.charAt(j); + if (c >= ' ' && c != '"') { + sb.append(c); + } + } + sb.append('"'); + } else { + sb.append(string); + } + } + } + sb.append('\n'); + return sb.toString(); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return toJSONArray(new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string, + * using the first row as a source of names. + * @param x The JSONTokener containing the comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONTokener x) throws JSONException { + return toJSONArray(rowToJSONArray(x), x); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param string The comma delimited text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONArray names, String string) + throws JSONException { + return toJSONArray(names, new JSONTokener(string)); + } + + /** + * Produce a JSONArray of JSONObjects from a comma delimited text string + * using a supplied JSONArray as the source of element names. + * @param names A JSONArray of strings. + * @param x A JSONTokener of the source text. + * @return A JSONArray of JSONObjects. + * @throws JSONException + */ + public static JSONArray toJSONArray(JSONArray names, JSONTokener x) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (;;) { + JSONObject jo = rowToJSONObject(names, x); + if (jo == null) { + break; + } + ja.put(jo); + } + if (ja.length() == 0) { + return null; + } + return ja; + } + + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects. The + * first row will be a list of names obtained by inspecting the first + * JSONObject. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException + */ + public static String toString(JSONArray ja) throws JSONException { + JSONObject jo = ja.optJSONObject(0); + if (jo != null) { + JSONArray names = jo.names(); + if (names != null) { + return rowToString(names) + toString(names, ja); + } + } + return null; + } + + /** + * Produce a comma delimited text from a JSONArray of JSONObjects using + * a provided list of names. The list of names is not included in the + * output. + * @param names A JSONArray of strings. + * @param ja A JSONArray of JSONObjects. + * @return A comma delimited text. + * @throws JSONException + */ + public static String toString(JSONArray names, JSONArray ja) + throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < ja.length(); i += 1) { + JSONObject jo = ja.optJSONObject(i); + if (jo != null) { + sb.append(rowToString(jo.toJSONArray(names))); + } + } + return sb.toString(); + } +} diff --git a/dot/org/json/Cookie.java b/dot/org/json/Cookie.java new file mode 100755 index 0000000..9cf5ce2 --- /dev/null +++ b/dot/org/json/Cookie.java @@ -0,0 +1,169 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Convert a web browser cookie specification to a JSONObject and back. + * JSON and Cookies are both notations for name/value pairs. + * @author JSON.org + * @version 2010-12-24 + */ +public class Cookie { + + /** + * Produce a copy of a string in which the characters '+', '%', '=', ';' + * and control characters are replaced with "%hh". This is a gentle form + * of URL encoding, attempting to cause as little distortion to the + * string as possible. The characters '=' and ';' are meta characters in + * cookies. By convention, they are escaped using the URL-encoding. This is + * only a convention, not a standard. Often, cookies are expected to have + * encoded values. We encode '=' and ';' because we must. We encode '%' and + * '+' because they are meta characters in URL encoding. + * @param string The source string. + * @return The escaped result. + */ + public static String escape(String string) { + char c; + String s = string.trim(); + StringBuffer sb = new StringBuffer(); + int length = s.length(); + for (int i = 0; i < length; i += 1) { + c = s.charAt(i); + if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { + sb.append('%'); + sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); + sb.append(Character.forDigit((char)(c & 0x0f), 16)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + + /** + * Convert a cookie specification string into a JSONObject. The string + * will contain a name value pair separated by '='. The name and the value + * will be unescaped, possibly converting '+' and '%' sequences. The + * cookie properties may follow, separated by ';', also represented as + * name=value (except the secure property, which does not have a value). + * The name will be stored under the key "name", and the value will be + * stored under the key "value". This method does not do checking or + * validation of the parameters. It only converts the cookie string into + * a JSONObject. + * @param string The cookie specification string. + * @return A JSONObject containing "name", "value", and possibly other + * members. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + String name; + JSONObject jo = new JSONObject(); + Object value; + JSONTokener x = new JSONTokener(string); + jo.put("name", x.nextTo('=')); + x.next('='); + jo.put("value", x.nextTo(';')); + x.next(); + while (x.more()) { + name = unescape(x.nextTo("=;")); + if (x.next() != '=') { + if (name.equals("secure")) { + value = Boolean.TRUE; + } else { + throw x.syntaxError("Missing '=' in cookie parameter."); + } + } else { + value = unescape(x.nextTo(';')); + x.next(); + } + jo.put(name, value); + } + return jo; + } + + + /** + * Convert a JSONObject into a cookie specification string. The JSONObject + * must contain "name" and "value" members. + * If the JSONObject contains "expires", "domain", "path", or "secure" + * members, they will be appended to the cookie specification string. + * All other members are ignored. + * @param jo A JSONObject + * @return A cookie specification string + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuffer sb = new StringBuffer(); + + sb.append(escape(jo.getString("name"))); + sb.append("="); + sb.append(escape(jo.getString("value"))); + if (jo.has("expires")) { + sb.append(";expires="); + sb.append(jo.getString("expires")); + } + if (jo.has("domain")) { + sb.append(";domain="); + sb.append(escape(jo.getString("domain"))); + } + if (jo.has("path")) { + sb.append(";path="); + sb.append(escape(jo.getString("path"))); + } + if (jo.optBoolean("secure")) { + sb.append(";secure"); + } + return sb.toString(); + } + + /** + * Convert %hh sequences to single characters, and + * convert plus to space. + * @param string A string that may contain + * + (plus) and + * %hh sequences. + * @return The unescaped string. + */ + public static String unescape(String string) { + int length = string.length(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; ++i) { + char c = string.charAt(i); + if (c == '+') { + c = ' '; + } else if (c == '%' && i + 2 < length) { + int d = JSONTokener.dehexchar(string.charAt(i + 1)); + int e = JSONTokener.dehexchar(string.charAt(i + 2)); + if (d >= 0 && e >= 0) { + c = (char)(d * 16 + e); + i += 2; + } + } + sb.append(c); + } + return sb.toString(); + } +} diff --git a/dot/org/json/CookieList.java b/dot/org/json/CookieList.java new file mode 100755 index 0000000..7f4fe07 --- /dev/null +++ b/dot/org/json/CookieList.java @@ -0,0 +1,90 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + +/** + * Convert a web browser cookie list string to a JSONObject and back. + * @author JSON.org + * @version 2010-12-24 + */ +public class CookieList { + + /** + * Convert a cookie list into a JSONObject. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The names and the values + * will be unescaped, possibly converting '+' and '%' sequences. + * + * To add a cookie to a cooklist, + * cookielistJSONObject.put(cookieJSONObject.getString("name"), + * cookieJSONObject.getString("value")); + * @param string A cookie list string + * @return A JSONObject + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + JSONTokener x = new JSONTokener(string); + while (x.more()) { + String name = Cookie.unescape(x.nextTo('=')); + x.next('='); + jo.put(name, Cookie.unescape(x.nextTo(';'))); + x.next(); + } + return jo; + } + + + /** + * Convert a JSONObject into a cookie list. A cookie list is a sequence + * of name/value pairs. The names are separated from the values by '='. + * The pairs are separated by ';'. The characters '%', '+', '=', and ';' + * in the names and values are replaced by "%hh". + * @param jo A JSONObject + * @return A cookie list string + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + boolean b = false; + Iterator keys = jo.keys(); + String string; + StringBuffer sb = new StringBuffer(); + while (keys.hasNext()) { + string = keys.next().toString(); + if (!jo.isNull(string)) { + if (b) { + sb.append(';'); + } + sb.append(Cookie.escape(string)); + sb.append("="); + sb.append(Cookie.escape(jo.getString(string))); + b = true; + } + } + return sb.toString(); + } +} diff --git a/dot/org/json/HTTP.java b/dot/org/json/HTTP.java new file mode 100755 index 0000000..43d04a8 --- /dev/null +++ b/dot/org/json/HTTP.java @@ -0,0 +1,163 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + +/** + * Convert an HTTP header to a JSONObject and back. + * @author JSON.org + * @version 2010-12-24 + */ +public class HTTP { + + /** Carriage return/line feed. */ + public static final String CRLF = "\r\n"; + + /** + * Convert an HTTP header string into a JSONObject. It can be a request + * header or a response header. A request header will contain + *

{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header will contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * In addition, the other parameters in the header will be captured, using + * the HTTP field names as JSON names, so that
+     *    Date: Sun, 26 May 2002 18:06:04 GMT
+     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
+     *    Cache-Control: no-cache
+ * become + *
{...
+     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
+     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
+     *    "Cache-Control": "no-cache",
+     * ...}
+ * It does no further checking or conversion. It does not parse dates. + * It does not do '%' transforms on URLs. + * @param string An HTTP header string. + * @return A JSONObject containing the elements and attributes + * of the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + HTTPTokener x = new HTTPTokener(string); + String token; + + token = x.nextToken(); + if (token.toUpperCase().startsWith("HTTP")) { + +// Response + + jo.put("HTTP-Version", token); + jo.put("Status-Code", x.nextToken()); + jo.put("Reason-Phrase", x.nextTo('\0')); + x.next(); + + } else { + +// Request + + jo.put("Method", token); + jo.put("Request-URI", x.nextToken()); + jo.put("HTTP-Version", x.nextToken()); + } + +// Fields + + while (x.more()) { + String name = x.nextTo(':'); + x.next(':'); + jo.put(name, x.nextTo('\0')); + x.next(); + } + return jo; + } + + + /** + * Convert a JSONObject into an HTTP header. A request header must contain + *
{
+     *    Method: "POST" (for example),
+     *    "Request-URI": "/" (for example),
+     *    "HTTP-Version": "HTTP/1.1" (for example)
+     * }
+ * A response header must contain + *
{
+     *    "HTTP-Version": "HTTP/1.1" (for example),
+     *    "Status-Code": "200" (for example),
+     *    "Reason-Phrase": "OK" (for example)
+     * }
+ * Any other members of the JSONObject will be output as HTTP fields. + * The result will end with two CRLF pairs. + * @param jo A JSONObject + * @return An HTTP header string. + * @throws JSONException if the object does not contain enough + * information. + */ + public static String toString(JSONObject jo) throws JSONException { + Iterator keys = jo.keys(); + String string; + StringBuffer sb = new StringBuffer(); + if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { + sb.append(jo.getString("HTTP-Version")); + sb.append(' '); + sb.append(jo.getString("Status-Code")); + sb.append(' '); + sb.append(jo.getString("Reason-Phrase")); + } else if (jo.has("Method") && jo.has("Request-URI")) { + sb.append(jo.getString("Method")); + sb.append(' '); + sb.append('"'); + sb.append(jo.getString("Request-URI")); + sb.append('"'); + sb.append(' '); + sb.append(jo.getString("HTTP-Version")); + } else { + throw new JSONException("Not enough material for an HTTP header."); + } + sb.append(CRLF); + while (keys.hasNext()) { + string = keys.next().toString(); + if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && + !"Reason-Phrase".equals(string) && !"Method".equals(string) && + !"Request-URI".equals(string) && !jo.isNull(string)) { + sb.append(string); + sb.append(": "); + sb.append(jo.getString(string)); + sb.append(CRLF); + } + } + sb.append(CRLF); + return sb.toString(); + } +} diff --git a/dot/org/json/HTTPTokener.java b/dot/org/json/HTTPTokener.java new file mode 100755 index 0000000..f62b3d5 --- /dev/null +++ b/dot/org/json/HTTPTokener.java @@ -0,0 +1,77 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The HTTPTokener extends the JSONTokener to provide additional methods + * for the parsing of HTTP headers. + * @author JSON.org + * @version 2010-12-24 + */ +public class HTTPTokener extends JSONTokener { + + /** + * Construct an HTTPTokener from a string. + * @param string A source string. + */ + public HTTPTokener(String string) { + super(string); + } + + + /** + * Get the next token or string. This is used in parsing HTTP headers. + * @throws JSONException + * @return A String. + */ + public String nextToken() throws JSONException { + char c; + char q; + StringBuffer sb = new StringBuffer(); + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == '"' || c == '\'') { + q = c; + for (;;) { + c = next(); + if (c < ' ') { + throw syntaxError("Unterminated string."); + } + if (c == q) { + return sb.toString(); + } + sb.append(c); + } + } + for (;;) { + if (c == 0 || Character.isWhitespace(c)) { + return sb.toString(); + } + sb.append(c); + c = next(); + } + } +} diff --git a/dot/org/json/JSONArray.class b/dot/org/json/JSONArray.class new file mode 100644 index 0000000000000000000000000000000000000000..83e6c9969cb05b848d6436f3b238b1765f0e822e GIT binary patch literal 9162 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 ze%xssget and opt + * methods for accessing the values by index, and put methods for + * adding or replacing values. The values can be any of these types: + * Boolean, JSONArray, JSONObject, + * Number, String, or the + * JSONObject.NULL object. + *

+ * The constructor can convert a JSON text into a Java object. The + * toString method converts to JSON text. + *

+ * A get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. + *

+ * The texts produced by the toString methods strictly conform to + * JSON syntax rules. The constructors are more forgiving in the texts they will + * accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing bracket.
  • + *
  • The null value will be inserted when there is , + *  (comma) elision.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , = ; # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
  • Values can be separated by ; (semicolon) as + * well as by , (comma).
  • + *
+ * + * @author JSON.org + * @version 2012-04-20 + */ +public class JSONArray { + + + /** + * The arrayList where the JSONArray's properties are kept. + */ + private final ArrayList myArrayList; + + + /** + * Construct an empty JSONArray. + */ + public JSONArray() { + this.myArrayList = new ArrayList(); + } + + /** + * Construct a JSONArray from a JSONTokener. + * @param x A JSONTokener + * @throws JSONException If there is a syntax error. + */ + public JSONArray(JSONTokener x) throws JSONException { + this(); + if (x.nextClean() != '[') { + throw x.syntaxError("A JSONArray text must start with '['"); + } + if (x.nextClean() != ']') { + x.back(); + for (;;) { + if (x.nextClean() == ',') { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } else { + x.back(); + this.myArrayList.add(x.nextValue()); + } + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == ']') { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); + } + } + } + } + + + /** + * Construct a JSONArray from a source JSON text. + * @param source A string that begins with + * [ (left bracket) + * and ends with ] (right bracket). + * @throws JSONException If there is a syntax error. + */ + public JSONArray(String source) throws JSONException { + this(new JSONTokener(source)); + } + + + /** + * Construct a JSONArray from a Collection. + * @param collection A Collection. + */ + public JSONArray(Collection collection) { + this.myArrayList = new ArrayList(); + if (collection != null) { + Iterator iter = collection.iterator(); + while (iter.hasNext()) { + this.myArrayList.add(JSONObject.wrap(iter.next())); + } + } + } + + + /** + * Construct a JSONArray from an array + * @throws JSONException If not an array. + */ + public JSONArray(Object array) throws JSONException { + this(); + if (array.getClass().isArray()) { + int length = Array.getLength(array); + for (int i = 0; i < length; i += 1) { + this.put(JSONObject.wrap(Array.get(array, i))); + } + } else { + throw new JSONException( +"JSONArray initial value should be a string or collection or array."); + } + } + + + /** + * Get the object value associated with an index. + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException If there is no value for the index. + */ + public Object get(int index) throws JSONException { + Object object = this.opt(index); + if (object == null) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + + /** + * Get the boolean value associated with an index. + * The string values "true" and "false" are converted to boolean. + * + * @param index The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException If there is no value for the index or if the + * value is not convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONArray[" + index + "] is not a boolean."); + } + + + /** + * Get the double value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value cannot + * be converted to a number. + */ + public double getDouble(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the int value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the JSONArray associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException If there is no value for the index. or if the + * value is not a JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONArray) { + return (JSONArray)object; + } + throw new JSONException("JSONArray[" + index + + "] is not a JSONArray."); + } + + + /** + * Get the JSONObject associated with an index. + * @param index subscript + * @return A JSONObject value. + * @throws JSONException If there is no value for the index or if the + * value is not a JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONObject) { + return (JSONObject)object; + } + throw new JSONException("JSONArray[" + index + + "] is not a JSONObject."); + } + + + /** + * Get the long value associated with an index. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException If the key is not found or if the value cannot + * be converted to a number. + */ + public long getLong(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number + ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] is not a number."); + } + } + + + /** + * Get the string associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException If there is no string value for the index. + */ + public String getString(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof String) { + return (String)object; + } + throw new JSONException("JSONArray[" + index + "] not a string."); + } + + + /** + * Determine if the value is null. + * @param index The index must be between 0 and length() - 1. + * @return true if the value at the index is null, or if there is no value. + */ + public boolean isNull(int index) { + return JSONObject.NULL.equals(this.opt(index)); + } + + + /** + * Make a string from the contents of this JSONArray. The + * separator string is inserted between each element. + * Warning: This method assumes that the data structure is acyclical. + * @param separator A string that will be inserted between the elements. + * @return a string. + * @throws JSONException If the array contains an invalid number. + */ + public String join(String separator) throws JSONException { + int len = this.length(); + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < len; i += 1) { + if (i > 0) { + sb.append(separator); + } + sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + } + return sb.toString(); + } + + + /** + * Get the number of elements in the JSONArray, included nulls. + * + * @return The length (or size). + */ + public int length() { + return this.myArrayList.size(); + } + + + /** + * Get the optional object value associated with an index. + * @param index The index must be between 0 and length() - 1. + * @return An object value, or null if there is no + * object at that index. + */ + public Object opt(int index) { + return (index < 0 || index >= this.length()) + ? null + : this.myArrayList.get(index); + } + + + /** + * Get the optional boolean value associated with an index. + * It returns false if there is no value at that index, + * or if the value is not Boolean.TRUE or the String "true". + * + * @param index The index must be between 0 and length() - 1. + * @return The truth. + */ + public boolean optBoolean(int index) { + return this.optBoolean(index, false); + } + + + /** + * Get the optional boolean value associated with an index. + * It returns the defaultValue if there is no value at that index or if + * it is not a Boolean or the String "true" or "false" (case insensitive). + * + * @param index The index must be between 0 and length() - 1. + * @param defaultValue A boolean default. + * @return The truth. + */ + public boolean optBoolean(int index, boolean defaultValue) { + try { + return this.getBoolean(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional double value associated with an index. + * NaN is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public double optDouble(int index) { + return this.optDouble(index, Double.NaN); + } + + + /** + * Get the optional double value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index subscript + * @param defaultValue The default value. + * @return The value. + */ + public double optDouble(int index, double defaultValue) { + try { + return this.getDouble(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional int value associated with an index. + * Zero is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public int optInt(int index) { + return this.optInt(index, 0); + } + + + /** + * Get the optional int value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return The value. + */ + public int optInt(int index, int defaultValue) { + try { + return this.getInt(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional JSONArray associated with an index. + * @param index subscript + * @return A JSONArray value, or null if the index has no value, + * or if the value is not a JSONArray. + */ + public JSONArray optJSONArray(int index) { + Object o = this.opt(index); + return o instanceof JSONArray ? (JSONArray)o : null; + } + + + /** + * Get the optional JSONObject associated with an index. + * Null is returned if the key is not found, or null if the index has + * no value, or if the value is not a JSONObject. + * + * @param index The index must be between 0 and length() - 1. + * @return A JSONObject value. + */ + public JSONObject optJSONObject(int index) { + Object o = this.opt(index); + return o instanceof JSONObject ? (JSONObject)o : null; + } + + + /** + * Get the optional long value associated with an index. + * Zero is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * + * @param index The index must be between 0 and length() - 1. + * @return The value. + */ + public long optLong(int index) { + return this.optLong(index, 0); + } + + + /** + * Get the optional long value associated with an index. + * The defaultValue is returned if there is no value for the index, + * or if the value is not a number and cannot be converted to a number. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return The value. + */ + public long optLong(int index, long defaultValue) { + try { + return this.getLong(index); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get the optional string value associated with an index. It returns an + * empty string if there is no value at that index. If the value + * is not a string and is not null, then it is coverted to a string. + * + * @param index The index must be between 0 and length() - 1. + * @return A String value. + */ + public String optString(int index) { + return this.optString(index, ""); + } + + + /** + * Get the optional string associated with an index. + * The defaultValue is returned if the key is not found. + * + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. + * @return A String value. + */ + public String optString(int index, String defaultValue) { + Object object = this.opt(index); + return JSONObject.NULL.equals(object) + ? defaultValue : object + .toString(); + } + + + /** + * Append a boolean value. This increases the array's length by one. + * + * @param value A boolean value. + * @return this. + */ + public JSONArray put(boolean value) { + this.put(value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONArray which is produced from a Collection. + * @param value A Collection value. + * @return this. + */ + public JSONArray put(Collection value) { + this.put(new JSONArray(value)); + return this; + } + + + /** + * Append a double value. This increases the array's length by one. + * + * @param value A double value. + * @throws JSONException if the value is not finite. + * @return this. + */ + public JSONArray put(double value) throws JSONException { + Double d = new Double(value); + JSONObject.testValidity(d); + this.put(d); + return this; + } + + + /** + * Append an int value. This increases the array's length by one. + * + * @param value An int value. + * @return this. + */ + public JSONArray put(int value) { + this.put(new Integer(value)); + return this; + } + + + /** + * Append an long value. This increases the array's length by one. + * + * @param value A long value. + * @return this. + */ + public JSONArray put(long value) { + this.put(new Long(value)); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONObject which is produced from a Map. + * @param value A Map value. + * @return this. + */ + public JSONArray put(Map value) { + this.put(new JSONObject(value)); + return this; + } + + + /** + * Append an object value. This increases the array's length by one. + * @param value An object value. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + */ + public JSONArray put(Object value) { + this.myArrayList.add(value); + return this; + } + + + /** + * Put or replace a boolean value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * @param index The subscript. + * @param value A boolean value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, boolean value) throws JSONException { + this.put(index, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONArray which is produced from a Collection. + * @param index The subscript. + * @param value A Collection value. + * @return this. + * @throws JSONException If the index is negative or if the value is + * not finite. + */ + public JSONArray put(int index, Collection value) throws JSONException { + this.put(index, new JSONArray(value)); + return this; + } + + + /** + * Put or replace a double value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value A double value. + * @return this. + * @throws JSONException If the index is negative or if the value is + * not finite. + */ + public JSONArray put(int index, double value) throws JSONException { + this.put(index, new Double(value)); + return this; + } + + + /** + * Put or replace an int value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value An int value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, int value) throws JSONException { + this.put(index, new Integer(value)); + return this; + } + + + /** + * Put or replace a long value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad + * it out. + * @param index The subscript. + * @param value A long value. + * @return this. + * @throws JSONException If the index is negative. + */ + public JSONArray put(int index, long value) throws JSONException { + this.put(index, new Long(value)); + return this; + } + + + /** + * Put a value in the JSONArray, where the value will be a + * JSONObject that is produced from a Map. + * @param index The subscript. + * @param value The Map value. + * @return this. + * @throws JSONException If the index is negative or if the the value is + * an invalid number. + */ + public JSONArray put(int index, Map value) throws JSONException { + this.put(index, new JSONObject(value)); + return this; + } + + + /** + * Put or replace an object value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * @param index The subscript. + * @param value The value to put into the array. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + * @throws JSONException If the index is negative or if the the value is + * an invalid number. + */ + public JSONArray put(int index, Object value) throws JSONException { + JSONObject.testValidity(value); + if (index < 0) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + if (index < this.length()) { + this.myArrayList.set(index, value); + } else { + while (index != this.length()) { + this.put(JSONObject.NULL); + } + this.put(value); + } + return this; + } + + + /** + * Remove an index and close the hole. + * @param index The index of the element to be removed. + * @return The value that was associated with the index, + * or null if there was no value. + */ + public Object remove(int index) { + Object o = this.opt(index); + this.myArrayList.remove(index); + return o; + } + + + /** + * Produce a JSONObject by combining a JSONArray of names with the values + * of this JSONArray. + * @param names A JSONArray containing a list of key strings. These will be + * paired with the values. + * @return A JSONObject, or null if there are no names or if this JSONArray + * has no values. + * @throws JSONException If any of the names are null. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + if (names == null || names.length() == 0 || this.length() == 0) { + return null; + } + JSONObject jo = new JSONObject(); + for (int i = 0; i < names.length(); i += 1) { + jo.put(names.getString(i), this.opt(i)); + } + return jo; + } + + + /** + * Make a JSON text of this JSONArray. For compactness, no + * unnecessary whitespace is added. If it is not possible to produce a + * syntactically correct JSON text then null will be returned instead. This + * could occur if the array contains an invalid number. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, transmittable + * representation of the array. + */ + public String toString() { + try { + return '[' + this.join(",") + ']'; + } catch (Exception e) { + return null; + } + } + + + /** + * Make a prettyprinted JSON text of this JSONArray. + * Warning: This method assumes that the data structure is acyclical. + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @return a printable, displayable, transmittable + * representation of the object, beginning + * with [ (left bracket) and ending + * with ] (right bracket). + * @throws JSONException + */ + public String toString(int indentFactor) throws JSONException { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + return this.write(sw, indentFactor, 0).toString(); + } + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indention of the top level. + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + int length = this.length(); + writer.write('['); + + if (length == 1) { + JSONObject.writeValue(writer, this.myArrayList.get(0), + indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + + for (int i = 0; i < length; i += 1) { + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, newindent); + JSONObject.writeValue(writer, this.myArrayList.get(i), + indentFactor, newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, indent); + } + writer.write(']'); + return writer; + } catch (IOException e) { + throw new JSONException(e); + } + } +} diff --git a/dot/org/json/JSONException.class b/dot/org/json/JSONException.class new file mode 100644 index 0000000000000000000000000000000000000000..61db0afc1768f7283d4f622d95e48f1a1d7d75e9 GIT binary patch literal 587 zcmY*W%TB^T6g^WYm0CdFh_C31M*@jkj2qNMg17+L4>+kMwKaXHpQVY9#DyQ=M;UKx zL!pa1GpFZq@66Bd*EfJ;9H@{{QBg%LjU=`e)D`S7Y`MZQxH%P$YuMJ!NSDW7~J;;=%~b3WM?W z==^yu9y}VW6ZEPfgRFvG4SU$vunCQ!Vmo?w;o4Srjn7bwr(3$Lq03|nrtYqU>vElf zOKbf_bK{V%Jh(&&b)=wxMhZ`9LZ}hiCkUhdsOIQ&M7Tt2s@47kd!-${6je1u^W;?s z`T2<7iTK%8`vVe5TJ3ivVqKQ}fik65D5XlO0*aA#k5)#1<<=V#FUzP@2-c~V2$N9$ E18ksnod5s; literal 0 HcmV?d00001 diff --git a/dot/org/json/JSONException.java b/dot/org/json/JSONException.java new file mode 100755 index 0000000..289b602 --- /dev/null +++ b/dot/org/json/JSONException.java @@ -0,0 +1,28 @@ +package org.json; + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * @author JSON.org + * @version 2010-12-24 + */ +public class JSONException extends Exception { + private static final long serialVersionUID = 0; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * @param message Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + public Throwable getCause() { + return this.cause; + } +} diff --git a/dot/org/json/JSONML.java b/dot/org/json/JSONML.java new file mode 100755 index 0000000..f29ee72 --- /dev/null +++ b/dot/org/json/JSONML.java @@ -0,0 +1,467 @@ +package org.json; + +/* +Copyright (c) 2008 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + + +/** + * This provides static methods to convert an XML text into a JSONArray or + * JSONObject, and to covert a JSONArray or JSONObject into an XML text using + * the JsonML transform. + * + * @author JSON.org + * @version 2012-03-28 + */ +public class JSONML { + + /** + * Parse XML values and store them in a JSONArray. + * @param x The XMLTokener containing the source string. + * @param arrayForm true if array form, false if object form. + * @param ja The JSONArray that is containing the current tag or null + * if we are at the outermost level. + * @return A JSONArray if the value is the outermost tag, otherwise null. + * @throws JSONException + */ + private static Object parse( + XMLTokener x, + boolean arrayForm, + JSONArray ja + ) throws JSONException { + String attribute; + char c; + String closeTag = null; + int i; + JSONArray newja = null; + JSONObject newjo = null; + Object token; + String tagName = null; + +// Test for and skip past these forms: +// +// +// +// + + while (true) { + if (!x.more()) { + throw x.syntaxError("Bad XML"); + } + token = x.nextContent(); + if (token == XML.LT) { + token = x.nextToken(); + if (token instanceof Character) { + if (token == XML.SLASH) { + +// Close tag "); + } else { + x.back(); + } + } else if (c == '[') { + token = x.nextToken(); + if (token.equals("CDATA") && x.next() == '[') { + if (ja != null) { + ja.put(x.nextCDATA()); + } + } else { + throw x.syntaxError("Expected 'CDATA['"); + } + } else { + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + } + } else if (token == XML.QUEST) { + +// "); + } else { + throw x.syntaxError("Misshaped tag"); + } + +// Open tag < + + } else { + if (!(token instanceof String)) { + throw x.syntaxError("Bad tagName '" + token + "'."); + } + tagName = (String)token; + newja = new JSONArray(); + newjo = new JSONObject(); + if (arrayForm) { + newja.put(tagName); + if (ja != null) { + ja.put(newja); + } + } else { + newjo.put("tagName", tagName); + if (ja != null) { + ja.put(newjo); + } + } + token = null; + for (;;) { + if (token == null) { + token = x.nextToken(); + } + if (token == null) { + throw x.syntaxError("Misshaped tag"); + } + if (!(token instanceof String)) { + break; + } + +// attribute = value + + attribute = (String)token; + if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { + throw x.syntaxError("Reserved attribute."); + } + token = x.nextToken(); + if (token == XML.EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + newjo.accumulate(attribute, XML.stringToValue((String)token)); + token = null; + } else { + newjo.accumulate(attribute, ""); + } + } + if (arrayForm && newjo.length() > 0) { + newja.put(newjo); + } + +// Empty tag <.../> + + if (token == XML.SLASH) { + if (x.nextToken() != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } + +// Content, between <...> and + + } else { + if (token != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + closeTag = (String)parse(x, arrayForm, newja); + if (closeTag != null) { + if (!closeTag.equals(tagName)) { + throw x.syntaxError("Mismatched '" + tagName + + "' and '" + closeTag + "'"); + } + tagName = null; + if (!arrayForm && newja.length() > 0) { + newjo.put("childNodes", newja); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } + } + } + } + } else { + if (ja != null) { + ja.put(token instanceof String + ? XML.stringToValue((String)token) + : token); + } + } + } + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child tags. + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param string The source string. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJSONArray(String string) throws JSONException { + return toJSONArray(new XMLTokener(string)); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONArray using the JsonML transform. Each XML tag is represented as + * a JSONArray in which the first element is the tag name. If the tag has + * attributes, then the second element will be JSONObject containing the + * name/value pairs. If the tag contains children, then strings and + * JSONArrays will represent the child content and tags. + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param x An XMLTokener. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJSONArray(XMLTokener x) throws JSONException { + return (JSONArray)parse(x, true, null); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param x An XMLTokener of the XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(XMLTokener x) throws JSONException { + return (JSONObject)parse(x, false, null); + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject using the JsonML transform. Each XML tag is represented as + * a JSONObject with a "tagName" property. If the tag has attributes, then + * the attributes will be in the JSONObject as properties. If the tag + * contains children, the object will have a "childNodes" property which + * will be an array of strings and JsonML JSONObjects. + + * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * @param string The XML source text. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + return toJSONObject(new XMLTokener(string)); + } + + + /** + * Reverse the JSONML transformation, making an XML text from a JSONArray. + * @param ja A JSONArray. + * @return An XML string. + * @throws JSONException + */ + public static String toString(JSONArray ja) throws JSONException { + int i; + JSONObject jo; + String key; + Iterator keys; + int length; + Object object; + StringBuffer sb = new StringBuffer(); + String tagName; + String value; + +// Emit = length) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + do { + object = ja.get(i); + i += 1; + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } + } + } while (i < length); + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } + + /** + * Reverse the JSONML transformation, making an XML text from a JSONObject. + * The JSONObject must contain a "tagName" property. If it has children, + * then it must have a "childNodes" property containing an array of objects. + * The other properties are attributes with string values. + * @param jo A JSONObject. + * @return An XML string. + * @throws JSONException + */ + public static String toString(JSONObject jo) throws JSONException { + StringBuffer sb = new StringBuffer(); + int i; + JSONArray ja; + String key; + Iterator keys; + int length; + Object object; + String tagName; + String value; + +//Emit '); + } else { + sb.append('>'); + length = ja.length(); + for (i = 0; i < length; i += 1) { + object = ja.get(i); + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } else { + sb.append(object.toString()); + } + } + } + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } + return sb.toString(); + } +} diff --git a/dot/org/json/JSONObject$1.class b/dot/org/json/JSONObject$1.class new file mode 100644 index 0000000000000000000000000000000000000000..64c0e8fc984702841f9e103c6212c0616f9c9baa GIT binary patch literal 199 zcmX^0Z`VEs1_mPr9(D$Hb_Om+2Cm@z(xT*4x6GVWMh1SbV1GaVq^#8B61}X%vP7VW zYhH3resN}Ax^HSpMt%xA12-dsXns+;epYdQo<2goiXkHd10w^EXI@@vk#kOBadB!f zBZC0Q6#bmUymWntv5XADSTqYL0JSm!9R>o-K*#{(u`sX#X%+@HAjt{DTtGF9Af5mR E00_A(^Z)<= literal 0 HcmV?d00001 diff --git a/dot/org/json/JSONObject$Null.class b/dot/org/json/JSONObject$Null.class new file mode 100644 index 0000000000000000000000000000000000000000..eb7d3742de52026cd9f35e43bb555c3ab6ef82a6 GIT binary patch literal 656 zcmZutJx{_=6g{s6S}IuNL!kJvIPj5(=!h{UBqkb!p~k_jU?s)+s%B?V)vV)m@7Z>fPSZ?uSj1vF}Ef8!+U`^X~x8r%qSbduZ**aZ(-|8VuaJd?CAtf$K`5wF^>v2Fsh&V`%G)CY zi5PnA3u>+U1SRr}i2Nc(|A{|fnJO{JarsaP>qt!nN`%5lPRp}Sk0~*dof1WO;UvPd a`S22QW6xD&2-8GeK@mu)^cO{xVEh6ptae}k literal 0 HcmV?d00001 diff --git a/dot/org/json/JSONObject.class b/dot/org/json/JSONObject.class new file mode 100644 index 0000000000000000000000000000000000000000..0393352d40d455cdf8aa5094900778d208c22927 GIT binary patch literal 17385 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 S<|@O7Tmz6K?h{Q;_x}OfJSF%5 literal 0 HcmV?d00001 diff --git a/dot/org/json/JSONObject.java b/dot/org/json/JSONObject.java new file mode 100755 index 0000000..ffe5315 --- /dev/null +++ b/dot/org/json/JSONObject.java @@ -0,0 +1,1593 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * A JSONObject is an unordered collection of name/value pairs. Its external + * form is a string wrapped in curly braces with colons between the names and + * values, and commas between the values and names. The internal form is an + * object having get and opt methods for accessing the + * values by name, and put methods for adding or replacing values + * by name. The values can be any of these types: Boolean, + * JSONArray, JSONObject, Number, + * String, or the JSONObject.NULL object. A JSONObject + * constructor can be used to convert an external form JSON text into an + * internal form whose values can be retrieved with the get and + * opt methods, or to convert values into a JSON text using the + * put and toString methods. A get method + * returns a value if one can be found, and throws an exception if one cannot be + * found. An opt method returns a default value instead of throwing + * an exception, and so is useful for obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object, which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. The opt methods differ from the get methods in that they do + * not throw. Instead, they return a specified value, such as null. + *

+ * The put methods add or replace values in an object. For example, + * + *

+ * myString = new JSONObject().put("JSON", "Hello, World!").toString();
+ * 
+ * + * produces the string {"JSON": "Hello, World"}. + *

+ * The texts produced by the toString methods strictly conform to + * the JSON syntax rules. The constructors are more forgiving in the texts they + * will accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing brace.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , = ; # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
  • Keys can be followed by = or => as well as by + * :.
  • + *
  • Values can be followed by ; (semicolon) as + * well as by , (comma).
  • + *
+ * + * @author JSON.org + * @version 2012-07-02 + */ +public class JSONObject { + + /** + * JSONObject.NULL is equivalent to the value that JavaScript calls null, + * whilst Java's null is equivalent to the value that JavaScript calls + * undefined. + */ + private static final class Null { + + /** + * There is only intended to be a single instance of the NULL object, + * so the clone method returns itself. + * @return NULL. + */ + protected final Object clone() { + return this; + } + + /** + * A Null object is equal to the null value and to itself. + * @param object An object to test for nullness. + * @return true if the object parameter is the JSONObject.NULL object + * or null. + */ + public boolean equals(Object object) { + return object == null || object == this; + } + + /** + * Get the "null" string value. + * @return The string "null". + */ + public String toString() { + return "null"; + } + } + + + /** + * The map where the JSONObject's properties are kept. + */ + private final Map map; + + + /** + * It is sometimes more convenient and less ambiguous to have a + * NULL object than to use Java's null value. + * JSONObject.NULL.equals(null) returns true. + * JSONObject.NULL.toString() returns "null". + */ + public static final Object NULL = new Null(); + + + /** + * Construct an empty JSONObject. + */ + public JSONObject() { + this.map = new HashMap(); + } + + + /** + * Construct a JSONObject from a subset of another JSONObject. + * An array of strings is used to identify the keys that should be copied. + * Missing keys are ignored. + * @param jo A JSONObject. + * @param names An array of strings. + * @throws JSONException + * @exception JSONException If a value is a non-finite number or if a name is duplicated. + */ + public JSONObject(JSONObject jo, String[] names) { + this(); + for (int i = 0; i < names.length; i += 1) { + try { + this.putOnce(names[i], jo.opt(names[i])); + } catch (Exception ignore) { + } + } + } + + + /** + * Construct a JSONObject from a JSONTokener. + * @param x A JSONTokener object containing the source string. + * @throws JSONException If there is a syntax error in the source string + * or a duplicated key. + */ + public JSONObject(JSONTokener x) throws JSONException { + this(); + char c; + String key; + + if (x.nextClean() != '{') { + throw x.syntaxError("A JSONObject text must begin with '{'"); + } + for (;;) { + c = x.nextClean(); + switch (c) { + case 0: + throw x.syntaxError("A JSONObject text must end with '}'"); + case '}': + return; + default: + x.back(); + key = x.nextValue().toString(); + } + +// The key is followed by ':'. We will also tolerate '=' or '=>'. + + c = x.nextClean(); + if (c == '=') { + if (x.next() != '>') { + x.back(); + } + } else if (c != ':') { + throw x.syntaxError("Expected a ':' after a key"); + } + this.putOnce(key, x.nextValue()); + +// Pairs are separated by ','. We will also tolerate ';'. + + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == '}') { + return; + } + x.back(); + break; + case '}': + return; + default: + throw x.syntaxError("Expected a ',' or '}'"); + } + } + } + + + /** + * Construct a JSONObject from a Map. + * + * @param map A map object that can be used to initialize the contents of + * the JSONObject. + * @throws JSONException + */ + public JSONObject(Map map) { + this.map = new HashMap(); + if (map != null) { + Iterator i = map.entrySet().iterator(); + while (i.hasNext()) { + Map.Entry e = (Map.Entry)i.next(); + Object value = e.getValue(); + if (value != null) { + this.map.put(e.getKey(), wrap(value)); + } + } + } + } + + + /** + * Construct a JSONObject from an Object using bean getters. + * It reflects on all of the public methods of the object. + * For each of the methods with no parameters and a name starting + * with "get" or "is" followed by an uppercase letter, + * the method is invoked, and a key and the value returned from the getter method + * are put into the new JSONObject. + * + * The key is formed by removing the "get" or "is" prefix. + * If the second remaining character is not upper case, then the first + * character is converted to lower case. + * + * For example, if an object has a method named "getName", and + * if the result of calling object.getName() is "Larry Fine", + * then the JSONObject will contain "name": "Larry Fine". + * + * @param bean An object that has getter methods that should be used + * to make a JSONObject. + */ + public JSONObject(Object bean) { + this(); + this.populateMap(bean); + } + + + /** + * Construct a JSONObject from an Object, using reflection to find the + * public members. The resulting JSONObject's keys will be the strings + * from the names array, and the values will be the field values associated + * with those keys in the object. If a key is not found or not visible, + * then it will not be copied into the new JSONObject. + * @param object An object that has fields that should be used to make a + * JSONObject. + * @param names An array of strings, the names of the fields to be obtained + * from the object. + */ + public JSONObject(Object object, String names[]) { + this(); + Class c = object.getClass(); + for (int i = 0; i < names.length; i += 1) { + String name = names[i]; + try { + this.putOpt(name, c.getField(name).get(object)); + } catch (Exception ignore) { + } + } + } + + + /** + * Construct a JSONObject from a source JSON text string. + * This is the most commonly used JSONObject constructor. + * @param source A string beginning + * with { (left brace) and ending + * with } (right brace). + * @exception JSONException If there is a syntax error in the source + * string or a duplicated key. + */ + public JSONObject(String source) throws JSONException { + this(new JSONTokener(source)); + } + + + /** + * Construct a JSONObject from a ResourceBundle. + * @param baseName The ResourceBundle base name. + * @param locale The Locale to load the ResourceBundle for. + * @throws JSONException If any JSONExceptions are detected. + */ + public JSONObject(String baseName, Locale locale) throws JSONException { + this(); + ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + Thread.currentThread().getContextClassLoader()); + +// Iterate through the keys in the bundle. + + Enumeration keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + if (key instanceof String) { + +// Go through the path, ensuring that there is a nested JSONObject for each +// segment except the last. Add the value using the last segment's name into +// the deepest nested JSONObject. + + String[] path = ((String)key).split("\\."); + int last = path.length - 1; + JSONObject target = this; + for (int i = 0; i < last; i += 1) { + String segment = path[i]; + JSONObject nextTarget = target.optJSONObject(segment); + if (nextTarget == null) { + nextTarget = new JSONObject(); + target.put(segment, nextTarget); + } + target = nextTarget; + } + target.put(path[last], bundle.getString((String)key)); + } + } + } + + + /** + * Accumulate values under a key. It is similar to the put method except + * that if there is already an object stored under the key then a + * JSONArray is stored under the key to hold all of the accumulated values. + * If there is already a JSONArray, then the new value is appended to it. + * In contrast, the put method replaces the previous value. + * + * If only one value is accumulated that is not a JSONArray, then the + * result will be the same as using put. But if multiple values are + * accumulated, then the result will be like append. + * @param key A key string. + * @param value An object to be accumulated under the key. + * @return this. + * @throws JSONException If the value is an invalid number + * or if the key is null. + */ + public JSONObject accumulate( + String key, + Object value + ) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, value instanceof JSONArray + ? new JSONArray().put(value) + : value); + } else if (object instanceof JSONArray) { + ((JSONArray)object).put(value); + } else { + this.put(key, new JSONArray().put(object).put(value)); + } + return this; + } + + + /** + * Append values to the array under a key. If the key does not exist in the + * JSONObject, then the key is put in the JSONObject with its value being a + * JSONArray containing the value parameter. If the key was already + * associated with a JSONArray, then the value parameter is appended to it. + * @param key A key string. + * @param value An object to be accumulated under the key. + * @return this. + * @throws JSONException If the key is null or if the current value + * associated with the key is not a JSONArray. + */ + public JSONObject append(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, new JSONArray().put(value)); + } else if (object instanceof JSONArray) { + this.put(key, ((JSONArray)object).put(value)); + } else { + throw new JSONException("JSONObject[" + key + + "] is not a JSONArray."); + } + return this; + } + + + /** + * Produce a string from a double. The string "null" will be returned if + * the number is not finite. + * @param d A double. + * @return A String. + */ + public static String doubleToString(double d) { + if (Double.isInfinite(d) || Double.isNaN(d)) { + return "null"; + } + +// Shave off trailing zeros and decimal point, if possible. + + String string = Double.toString(d); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + + /** + * Get the value object associated with a key. + * + * @param key A key string. + * @return The object associated with the key. + * @throws JSONException if the key is not found. + */ + public Object get(String key) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + Object object = this.opt(key); + if (object == null) { + throw new JSONException("JSONObject[" + quote(key) + + "] not found."); + } + return object; + } + + + /** + * Get the boolean value associated with a key. + * + * @param key A key string. + * @return The truth. + * @throws JSONException + * if the value is not a Boolean or the String "true" or "false". + */ + public boolean getBoolean(String key) throws JSONException { + Object object = this.get(key); + if (object.equals(Boolean.FALSE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) || + (object instanceof String && + ((String)object).equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a Boolean."); + } + + + /** + * Get the double value associated with a key. + * @param key A key string. + * @return The numeric value. + * @throws JSONException if the key is not found or + * if the value is not a Number object and cannot be converted to a number. + */ + public double getDouble(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a number."); + } + } + + + /** + * Get the int value associated with a key. + * + * @param key A key string. + * @return The integer value. + * @throws JSONException if the key is not found or if the value cannot + * be converted to an integer. + */ + public int getInt(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not an int."); + } + } + + + /** + * Get the JSONArray value associated with a key. + * + * @param key A key string. + * @return A JSONArray which is the value. + * @throws JSONException if the key is not found or + * if the value is not a JSONArray. + */ + public JSONArray getJSONArray(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONArray) { + return (JSONArray)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONArray."); + } + + + /** + * Get the JSONObject value associated with a key. + * + * @param key A key string. + * @return A JSONObject which is the value. + * @throws JSONException if the key is not found or + * if the value is not a JSONObject. + */ + public JSONObject getJSONObject(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONObject) { + return (JSONObject)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONObject."); + } + + + /** + * Get the long value associated with a key. + * + * @param key A key string. + * @return The long value. + * @throws JSONException if the key is not found or if the value cannot + * be converted to a long. + */ + public long getLong(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number + ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a long."); + } + } + + + /** + * Get an array of field names from a JSONObject. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(JSONObject jo) { + int length = jo.length(); + if (length == 0) { + return null; + } + Iterator iterator = jo.keys(); + String[] names = new String[length]; + int i = 0; + while (iterator.hasNext()) { + names[i] = (String)iterator.next(); + i += 1; + } + return names; + } + + + /** + * Get an array of field names from an Object. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(Object object) { + if (object == null) { + return null; + } + Class klass = object.getClass(); + Field[] fields = klass.getFields(); + int length = fields.length; + if (length == 0) { + return null; + } + String[] names = new String[length]; + for (int i = 0; i < length; i += 1) { + names[i] = fields[i].getName(); + } + return names; + } + + + /** + * Get the string associated with a key. + * + * @param key A key string. + * @return A string which is the value. + * @throws JSONException if there is no string value for the key. + */ + public String getString(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof String) { + return (String)object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] not a string."); + } + + + /** + * Determine if the JSONObject contains a specific key. + * @param key A key string. + * @return true if the key exists in the JSONObject. + */ + public boolean has(String key) { + return this.map.containsKey(key); + } + + + /** + * Increment a property of a JSONObject. If there is no such property, + * create one with a value of 1. If there is such a property, and if + * it is an Integer, Long, Double, or Float, then add one to it. + * @param key A key string. + * @return this. + * @throws JSONException If there is already a property with this name + * that is not an Integer, Long, Double, or Float. + */ + public JSONObject increment(String key) throws JSONException { + Object value = this.opt(key); + if (value == null) { + this.put(key, 1); + } else if (value instanceof Integer) { + this.put(key, ((Integer)value).intValue() + 1); + } else if (value instanceof Long) { + this.put(key, ((Long)value).longValue() + 1); + } else if (value instanceof Double) { + this.put(key, ((Double)value).doubleValue() + 1); + } else if (value instanceof Float) { + this.put(key, ((Float)value).floatValue() + 1); + } else { + throw new JSONException("Unable to increment [" + quote(key) + "]."); + } + return this; + } + + + /** + * Determine if the value associated with the key is null or if there is + * no value. + * @param key A key string. + * @return true if there is no value associated with the key or if + * the value is the JSONObject.NULL object. + */ + public boolean isNull(String key) { + return JSONObject.NULL.equals(this.opt(key)); + } + + + /** + * Get an enumeration of the keys of the JSONObject. + * + * @return An iterator of the keys. + */ + public Iterator keys() { + return this.map.keySet().iterator(); + } + + + /** + * Get the number of keys stored in the JSONObject. + * + * @return The number of keys in the JSONObject. + */ + public int length() { + return this.map.size(); + } + + + /** + * Produce a JSONArray containing the names of the elements of this + * JSONObject. + * @return A JSONArray containing the key strings, or null if the JSONObject + * is empty. + */ + public JSONArray names() { + JSONArray ja = new JSONArray(); + Iterator keys = this.keys(); + while (keys.hasNext()) { + ja.put(keys.next()); + } + return ja.length() == 0 ? null : ja; + } + + /** + * Produce a string from a Number. + * @param number A Number + * @return A String. + * @throws JSONException If n is a non-finite number. + */ + public static String numberToString(Number number) + throws JSONException { + if (number == null) { + throw new JSONException("Null pointer"); + } + testValidity(number); + +// Shave off trailing zeros and decimal point, if possible. + + String string = number.toString(); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + + /** + * Get an optional value associated with a key. + * @param key A key string. + * @return An object which is the value, or null if there is no value. + */ + public Object opt(String key) { + return key == null ? null : this.map.get(key); + } + + + /** + * Get an optional boolean associated with a key. + * It returns false if there is no such key, or if the value is not + * Boolean.TRUE or the String "true". + * + * @param key A key string. + * @return The truth. + */ + public boolean optBoolean(String key) { + return this.optBoolean(key, false); + } + + + /** + * Get an optional boolean associated with a key. + * It returns the defaultValue if there is no such key, or if it is not + * a Boolean or the String "true" or "false" (case insensitive). + * + * @param key A key string. + * @param defaultValue The default. + * @return The truth. + */ + public boolean optBoolean(String key, boolean defaultValue) { + try { + return this.getBoolean(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional double associated with a key, + * or NaN if there is no such key or if its value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A string which is the key. + * @return An object which is the value. + */ + public double optDouble(String key) { + return this.optDouble(key, Double.NaN); + } + + + /** + * Get an optional double associated with a key, or the + * defaultValue if there is no such key or if its value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public double optDouble(String key, double defaultValue) { + try { + return this.getDouble(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional int value associated with a key, + * or zero if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @return An object which is the value. + */ + public int optInt(String key) { + return this.optInt(key, 0); + } + + + /** + * Get an optional int value associated with a key, + * or the default if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public int optInt(String key, int defaultValue) { + try { + return this.getInt(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional JSONArray associated with a key. + * It returns null if there is no such key, or if its value is not a + * JSONArray. + * + * @param key A key string. + * @return A JSONArray which is the value. + */ + public JSONArray optJSONArray(String key) { + Object o = this.opt(key); + return o instanceof JSONArray ? (JSONArray)o : null; + } + + + /** + * Get an optional JSONObject associated with a key. + * It returns null if there is no such key, or if its value is not a + * JSONObject. + * + * @param key A key string. + * @return A JSONObject which is the value. + */ + public JSONObject optJSONObject(String key) { + Object object = this.opt(key); + return object instanceof JSONObject ? (JSONObject)object : null; + } + + + /** + * Get an optional long value associated with a key, + * or zero if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @return An object which is the value. + */ + public long optLong(String key) { + return this.optLong(key, 0); + } + + + /** + * Get an optional long value associated with a key, + * or the default if there is no such key or if the value is not a number. + * If the value is a string, an attempt will be made to evaluate it as + * a number. + * + * @param key A key string. + * @param defaultValue The default. + * @return An object which is the value. + */ + public long optLong(String key, long defaultValue) { + try { + return this.getLong(key); + } catch (Exception e) { + return defaultValue; + } + } + + + /** + * Get an optional string associated with a key. + * It returns an empty string if there is no such key. If the value is not + * a string and is not null, then it is converted to a string. + * + * @param key A key string. + * @return A string which is the value. + */ + public String optString(String key) { + return this.optString(key, ""); + } + + + /** + * Get an optional string associated with a key. + * It returns the defaultValue if there is no such key. + * + * @param key A key string. + * @param defaultValue The default. + * @return A string which is the value. + */ + public String optString(String key, String defaultValue) { + Object object = this.opt(key); + return NULL.equals(object) ? defaultValue : object.toString(); + } + + + private void populateMap(Object bean) { + Class klass = bean.getClass(); + +// If klass is a System class then set includeSuperClass to false. + + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass + ? klass.getMethods() + : klass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i += 1) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || + "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && + Character.isUpperCase(key.charAt(0)) && + method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + + key.substring(1); + } + + Object result = method.invoke(bean, (Object[])null); + if (result != null) { + this.map.put(key, wrap(result)); + } + } + } + } catch (Exception ignore) { + } + } + } + + + /** + * Put a key/boolean pair in the JSONObject. + * + * @param key A key string. + * @param value A boolean which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, boolean value) throws JSONException { + this.put(key, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONArray which is produced from a Collection. + * @param key A key string. + * @param value A Collection value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Collection value) throws JSONException { + this.put(key, new JSONArray(value)); + return this; + } + + + /** + * Put a key/double pair in the JSONObject. + * + * @param key A key string. + * @param value A double which is the value. + * @return this. + * @throws JSONException If the key is null or if the number is invalid. + */ + public JSONObject put(String key, double value) throws JSONException { + this.put(key, new Double(value)); + return this; + } + + + /** + * Put a key/int pair in the JSONObject. + * + * @param key A key string. + * @param value An int which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, int value) throws JSONException { + this.put(key, new Integer(value)); + return this; + } + + + /** + * Put a key/long pair in the JSONObject. + * + * @param key A key string. + * @param value A long which is the value. + * @return this. + * @throws JSONException If the key is null. + */ + public JSONObject put(String key, long value) throws JSONException { + this.put(key, new Long(value)); + return this; + } + + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONObject which is produced from a Map. + * @param key A key string. + * @param value A Map value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Map value) throws JSONException { + this.put(key, new JSONObject(value)); + return this; + } + + + /** + * Put a key/value pair in the JSONObject. If the value is null, + * then the key will be removed from the JSONObject if it is present. + * @param key A key string. + * @param value An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, + * or the JSONObject.NULL object. + * @return this. + * @throws JSONException If the value is non-finite number + * or if the key is null. + */ + public JSONObject put(String key, Object value) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + if (value != null) { + testValidity(value); + this.map.put(key, value); + } else { + this.remove(key); + } + return this; + } + + + /** + * Put a key/value pair in the JSONObject, but only if the key and the + * value are both non-null, and only if there is not already a member + * with that name. + * @param key + * @param value + * @return his. + * @throws JSONException if the key is a duplicate + */ + public JSONObject putOnce(String key, Object value) throws JSONException { + if (key != null && value != null) { + if (this.opt(key) != null) { + throw new JSONException("Duplicate key \"" + key + "\""); + } + this.put(key, value); + } + return this; + } + + + /** + * Put a key/value pair in the JSONObject, but only if the + * key and the value are both non-null. + * @param key A key string. + * @param value An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, + * or the JSONObject.NULL object. + * @return this. + * @throws JSONException If the value is a non-finite number. + */ + public JSONObject putOpt(String key, Object value) throws JSONException { + if (key != null && value != null) { + this.put(key, value); + } + return this; + } + + + /** + * Produce a string in double quotes with backslash sequences in all the + * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') + || (c >= '\u2000' && c < '\u2100')) { + hhhh = "000" + Integer.toHexString(c); + w.write("\\u" + hhhh.substring(hhhh.length() - 4)); + } else { + w.write(c); + } + } + } + w.write('"'); + return w; + } + + /** + * Remove a name and its value, if present. + * @param key The name to be removed. + * @return The value that was associated with the name, + * or null if there was no value. + */ + public Object remove(String key) { + return this.map.remove(key); + } + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. + * @param string A String. + * @return A simple JSON value. + */ + public static Object stringToValue(String string) { + Double d; + if (string.equals("")) { + return string; + } + if (string.equalsIgnoreCase("true")) { + return Boolean.TRUE; + } + if (string.equalsIgnoreCase("false")) { + return Boolean.FALSE; + } + if (string.equalsIgnoreCase("null")) { + return JSONObject.NULL; + } + + /* + * If it might be a number, try converting it. + * If a number cannot be produced, then the value will just + * be a string. Note that the plus and implied string + * conventions are non-standard. A JSON parser may accept + * non-JSON forms as long as it accepts all correct JSON forms. + */ + + char b = string.charAt(0); + if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { + try { + if (string.indexOf('.') > -1 || + string.indexOf('e') > -1 || string.indexOf('E') > -1) { + d = Double.valueOf(string); + if (!d.isInfinite() && !d.isNaN()) { + return d; + } + } else { + Long myLong = new Long(string); + if (myLong.longValue() == myLong.intValue()) { + return new Integer(myLong.intValue()); + } else { + return myLong; + } + } + } catch (Exception ignore) { + } + } + return string; + } + + + /** + * Throw an exception if the object is a NaN or infinite number. + * @param o The object to test. + * @throws JSONException If o is a non-finite number. + */ + public static void testValidity(Object o) throws JSONException { + if (o != null) { + if (o instanceof Double) { + if (((Double)o).isInfinite() || ((Double)o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } else if (o instanceof Float) { + if (((Float)o).isInfinite() || ((Float)o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } + } + } + + + /** + * Produce a JSONArray containing the values of the members of this + * JSONObject. + * @param names A JSONArray containing a list of key strings. This + * determines the sequence of the values in the result. + * @return A JSONArray of values. + * @throws JSONException If any of the values are non-finite numbers. + */ + public JSONArray toJSONArray(JSONArray names) throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (int i = 0; i < names.length(); i += 1) { + ja.put(this.opt(names.getString(i))); + } + return ja; + } + + /** + * Make a JSON text of this JSONObject. For compactness, no whitespace + * is added. If this would not result in a syntactically correct JSON text, + * then null will be returned instead. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, portable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + */ + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + + /** + * Make a prettyprinted JSON text of this JSONObject. + *

+ * Warning: This method assumes that the data structure is acyclical. + * @param indentFactor The number of spaces to add to each level of + * indentation. + * @return a printable, displayable, portable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + * @throws JSONException If the object contains an invalid number. + */ + public String toString(int indentFactor) throws JSONException { + StringWriter w = new StringWriter(); + synchronized (w.getBuffer()) { + return this.write(w, indentFactor, 0).toString(); + } + } + + /** + * Make a JSON text of an Object value. If the object has an + * value.toJSONString() method, then that method will be used to produce + * the JSON text. The method is required to produce a strictly + * conforming text. If the object does not contain a toJSONString + * method (which is the most common case), then a text will be + * produced by other means. If the value is an array or Collection, + * then a JSONArray will be made from it and its toJSONString method + * will be called. If the value is a MAP, then a JSONObject will be made + * from it and its toJSONString method will be called. Otherwise, the + * value's toString method will be called, and the result will be quoted. + * + *

+ * Warning: This method assumes that the data structure is acyclical. + * @param value The value to be serialized. + * @return a printable, displayable, transmittable + * representation of the object, beginning + * with { (left brace) and ending + * with } (right brace). + * @throws JSONException If the value is or contains an invalid number. + */ + public static String valueToString(Object value) throws JSONException { + if (value == null || value.equals(null)) { + return "null"; + } + if (value instanceof JSONString) { + Object object; + try { + object = ((JSONString)value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + if (object instanceof String) { + return (String)object; + } + throw new JSONException("Bad value from toJSONString: " + object); + } + if (value instanceof Number) { + return numberToString((Number) value); + } + if (value instanceof Boolean || value instanceof JSONObject || + value instanceof JSONArray) { + return value.toString(); + } + if (value instanceof Map) { + return new JSONObject((Map)value).toString(); + } + if (value instanceof Collection) { + return new JSONArray((Collection)value).toString(); + } + if (value.getClass().isArray()) { + return new JSONArray(value).toString(); + } + return quote(value.toString()); + } + + /** + * Wrap an object, if necessary. If the object is null, return the NULL + * object. If it is an array or collection, wrap it in a JSONArray. If + * it is a map, wrap it in a JSONObject. If it is a standard property + * (Double, String, et al) then it is already wrapped. Otherwise, if it + * comes from one of the java packages, turn it into a string. And if + * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, + * then null is returned. + * + * @param object The object to wrap + * @return The wrapped value + */ + public static Object wrap(Object object) { + try { + if (object == null) { + return NULL; + } + if (object instanceof JSONObject || object instanceof JSONArray || + NULL.equals(object) || object instanceof JSONString || + object instanceof Byte || object instanceof Character || + object instanceof Short || object instanceof Integer || + object instanceof Long || object instanceof Boolean || + object instanceof Float || object instanceof Double || + object instanceof String || object instanceof Enum) { + return object; + } + + if (object instanceof Collection) { + return new JSONArray((Collection)object); + } + if (object.getClass().isArray()) { + return new JSONArray(object); + } + if (object instanceof Map) { + return new JSONObject((Map)object); + } + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null + ? objectPackage.getName() + : ""; + if ( + objectPackageName.startsWith("java.") || + objectPackageName.startsWith("javax.") || + object.getClass().getClassLoader() == null + ) { + return object.toString(); + } + return new JSONObject(object); + } catch(Exception exception) { + return null; + } + } + + + /** + * Write the contents of the JSONObject as JSON text to a writer. + * For compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + + static final Writer writeValue(Writer writer, Object value, + int indentFactor, int indent) throws JSONException, IOException { + if (value == null || value.equals(null)) { + writer.write("null"); + } else if (value instanceof JSONObject) { + ((JSONObject) value).write(writer, indentFactor, indent); + } else if (value instanceof JSONArray) { + ((JSONArray) value).write(writer, indentFactor, indent); + } else if (value instanceof Map) { + new JSONObject((Map) value).write(writer, indentFactor, indent); + } else if (value instanceof Collection) { + new JSONArray((Collection) value).write(writer, indentFactor, + indent); + } else if (value.getClass().isArray()) { + new JSONArray(value).write(writer, indentFactor, indent); + } else if (value instanceof Number) { + writer.write(numberToString((Number) value)); + } else if (value instanceof Boolean) { + writer.write(value.toString()); + } else if (value instanceof JSONString) { + Object o; + try { + o = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + writer.write(o != null ? o.toString() : quote(value.toString())); + } else { + quote(value.toString(), writer); + } + return writer; + } + + static final void indent(Writer writer, int indent) throws IOException { + for (int i = 0; i < indent; i += 1) { + writer.write(' '); + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + final int length = this.length(); + Iterator keys = this.keys(); + writer.write('{'); + + if (length == 1) { + Object key = keys.next(); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + while (keys.hasNext()) { + Object key = keys.next(); + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, newindent); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, + newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, indent); + } + writer.write('}'); + return writer; + } catch (IOException exception) { + throw new JSONException(exception); + } + } +} diff --git a/dot/org/json/JSONString.class b/dot/org/json/JSONString.class new file mode 100644 index 0000000000000000000000000000000000000000..329f686758d463a599abfa28eaaca9bd9cbc1e45 GIT binary patch literal 156 zcmX^0Z`VEs1_mPrPId-%b_Nbc2A-09uV8<_;F6-uymUqe5e-eBti-ZJ{hY+SbbW}Z zH6sI8aDHh~a;jTqPAVeJSONString interface allows a toJSONString() + * method so that a class can change the behavior of + * JSONObject.toString(), JSONArray.toString(), + * and JSONWriter.value(Object). The + * toJSONString method will be used instead of the default behavior + * of using the Object's toString() method and quoting the result. + */ +public interface JSONString { + /** + * The toJSONString method allows a class to produce its own JSON + * serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} diff --git a/dot/org/json/JSONStringer.java b/dot/org/json/JSONStringer.java new file mode 100755 index 0000000..25c2e5d --- /dev/null +++ b/dot/org/json/JSONStringer.java @@ -0,0 +1,78 @@ +package org.json; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.StringWriter; + +/** + * JSONStringer provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONStringer can produce one JSON text. + *

+ * A JSONStringer instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting cascade style. For example,

+ * myString = new JSONStringer()
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject()
+ *     .toString();
which produces the string
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONStringer adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2008-09-18 + */ +public class JSONStringer extends JSONWriter { + /** + * Make a fresh JSONStringer. It can be used to build one JSON text. + */ + public JSONStringer() { + super(new StringWriter()); + } + + /** + * Return the JSON text. This method is used to obtain the product of the + * JSONStringer instance. It will return null if there was a + * problem in the construction of the JSON text (such as the calls to + * array were not properly balanced with calls to + * endArray). + * @return The JSON text. + */ + public String toString() { + return this.mode == 'd' ? this.writer.toString() : null; + } +} diff --git a/dot/org/json/JSONTokener.class b/dot/org/json/JSONTokener.class new file mode 100644 index 0000000000000000000000000000000000000000..f886bccd67a198d4bf1ea742ab6390dc08d47cae GIT binary patch literal 5033 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 B8wLOX literal 0 HcmV?d00001 diff --git a/dot/org/json/JSONTokener.java b/dot/org/json/JSONTokener.java new file mode 100644 index 0000000..13c84f1 --- /dev/null +++ b/dot/org/json/JSONTokener.java @@ -0,0 +1,446 @@ +package org.json; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * A JSONTokener takes a source string and extracts characters and tokens from + * it. It is used by the JSONObject and JSONArray constructors to parse + * JSON source strings. + * @author JSON.org + * @version 2012-02-16 + */ +public class JSONTokener { + + private long character; + private boolean eof; + private long index; + private long line; + private char previous; + private Reader reader; + private boolean usePrevious; + + + /** + * Construct a JSONTokener from a Reader. + * + * @param reader A reader. + */ + public JSONTokener(Reader reader) { + this.reader = reader.markSupported() + ? reader + : new BufferedReader(reader); + this.eof = false; + this.usePrevious = false; + this.previous = 0; + this.index = 0; + this.character = 1; + this.line = 1; + } + + + /** + * Construct a JSONTokener from an InputStream. + */ + public JSONTokener(InputStream inputStream) throws JSONException { + this(new InputStreamReader(inputStream)); + } + + + /** + * Construct a JSONTokener from a string. + * + * @param s A source string. + */ + public JSONTokener(String s) { + this(new StringReader(s)); + } + + + /** + * Back up one character. This provides a sort of lookahead capability, + * so that you can test for a digit or letter before attempting to parse + * the next number or identifier. + */ + public void back() throws JSONException { + if (this.usePrevious || this.index <= 0) { + throw new JSONException("Stepping back two steps is not supported"); + } + this.index -= 1; + this.character -= 1; + this.usePrevious = true; + this.eof = false; + } + + + /** + * Get the hex value of a character (base16). + * @param c A character between '0' and '9' or between 'A' and 'F' or + * between 'a' and 'f'. + * @return An int between 0 and 15, or -1 if c was not a hex digit. + */ + public static int dehexchar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + if (c >= 'A' && c <= 'F') { + return c - ('A' - 10); + } + if (c >= 'a' && c <= 'f') { + return c - ('a' - 10); + } + return -1; + } + + public boolean end() { + return this.eof && !this.usePrevious; + } + + + /** + * Determine if the source string still contains characters that next() + * can consume. + * @return true if not yet at the end of the source. + */ + public boolean more() throws JSONException { + this.next(); + if (this.end()) { + return false; + } + this.back(); + return true; + } + + + /** + * Get the next character in the source string. + * + * @return The next character, or 0 if past the end of the source string. + */ + public char next() throws JSONException { + int c; + if (this.usePrevious) { + this.usePrevious = false; + c = this.previous; + } else { + try { + c = this.reader.read(); + } catch (IOException exception) { + throw new JSONException(exception); + } + + if (c <= 0) { // End of stream + this.eof = true; + c = 0; + } + } + this.index += 1; + if (this.previous == '\r') { + this.line += 1; + this.character = c == '\n' ? 0 : 1; + } else if (c == '\n') { + this.line += 1; + this.character = 0; + } else { + this.character += 1; + } + this.previous = (char) c; + return this.previous; + } + + + /** + * Consume the next character, and check that it matches a specified + * character. + * @param c The character to match. + * @return The character. + * @throws JSONException if the character does not match. + */ + public char next(char c) throws JSONException { + char n = this.next(); + if (n != c) { + throw this.syntaxError("Expected '" + c + "' and instead saw '" + + n + "'"); + } + return n; + } + + + /** + * Get the next n characters. + * + * @param n The number of characters to take. + * @return A string of n characters. + * @throws JSONException + * Substring bounds error if there are not + * n characters remaining in the source string. + */ + public String next(int n) throws JSONException { + if (n == 0) { + return ""; + } + + char[] chars = new char[n]; + int pos = 0; + + while (pos < n) { + chars[pos] = this.next(); + if (this.end()) { + throw this.syntaxError("Substring bounds error"); + } + pos += 1; + } + return new String(chars); + } + + + /** + * Get the next char in the string, skipping whitespace. + * @throws JSONException + * @return A character, or 0 if there are no more characters. + */ + public char nextClean() throws JSONException { + for (;;) { + char c = this.next(); + if (c == 0 || c > ' ') { + return c; + } + } + } + + + /** + * Return the characters up to the next close quote character. + * Backslash processing is done. The formal JSON format does not + * allow strings in single quotes, but an implementation is allowed to + * accept them. + * @param quote The quoting character, either + * " (double quote) or + * ' (single quote). + * @return A String. + * @throws JSONException Unterminated string. + */ + public String nextString(char quote) throws JSONException { + char c; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = this.next(); + switch (c) { + case 0: + case '\n': + case '\r': + throw this.syntaxError("Unterminated string"); + case '\\': + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + sb.append((char)Integer.parseInt(this.next(4), 16)); + break; + case '"': + case '\'': + case '\\': + case '/': + sb.append(c); + break; + default: + throw this.syntaxError("Illegal escape."); + } + break; + default: + if (c == quote) { + return sb.toString(); + } + sb.append(c); + } + } + } + + + /** + * Get the text up but not including the specified character or the + * end of line, whichever comes first. + * @param delimiter A delimiter character. + * @return A string. + */ + public String nextTo(char delimiter) throws JSONException { + StringBuffer sb = new StringBuffer(); + for (;;) { + char c = this.next(); + if (c == delimiter || c == 0 || c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the text up but not including one of the specified delimiter + * characters or the end of line, whichever comes first. + * @param delimiters A set of delimiter characters. + * @return A string, trimmed. + */ + public String nextTo(String delimiters) throws JSONException { + char c; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = this.next(); + if (delimiters.indexOf(c) >= 0 || c == 0 || + c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the next value. The value can be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. + * @throws JSONException If syntax error. + * + * @return An object. + */ + public Object nextValue() throws JSONException { + char c = this.nextClean(); + String string; + + switch (c) { + case '"': + case '\'': + return this.nextString(c); + case '{': + this.back(); + return new JSONObject(this); + case '[': + this.back(); + return new JSONArray(this); + } + + /* + * Handle unquoted text. This could be the values true, false, or + * null, or it can be a number. An implementation (such as this one) + * is allowed to also accept non-standard forms. + * + * Accumulate characters until we reach the end of the text or a + * formatting character. + */ + + StringBuffer sb = new StringBuffer(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = this.next(); + } + this.back(); + + string = sb.toString().trim(); + if ("".equals(string)) { + throw this.syntaxError("Missing value"); + } + return JSONObject.stringToValue(string); + } + + + /** + * Skip characters until the next character is the requested character. + * If the requested character is not found, no characters are skipped. + * @param to A character to skip to. + * @return The requested character, or zero if the requested character + * is not found. + */ + public char skipTo(char to) throws JSONException { + char c; + try { + long startIndex = this.index; + long startCharacter = this.character; + long startLine = this.line; + this.reader.mark(1000000); + do { + c = this.next(); + if (c == 0) { + this.reader.reset(); + this.index = startIndex; + this.character = startCharacter; + this.line = startLine; + return c; + } + } while (c != to); + } catch (IOException exc) { + throw new JSONException(exc); + } + + this.back(); + return c; + } + + + /** + * Make a JSONException to signal a syntax error. + * + * @param message The error message. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this.toString()); + } + + + /** + * Make a printable string of this JSONTokener. + * + * @return " at {index} [character {character} line {line}]" + */ + public String toString() { + return " at " + this.index + " [character " + this.character + " line " + + this.line + "]"; + } +} diff --git a/dot/org/json/JSONWriter.java b/dot/org/json/JSONWriter.java new file mode 100755 index 0000000..855b2bd --- /dev/null +++ b/dot/org/json/JSONWriter.java @@ -0,0 +1,327 @@ +package org.json; + +import java.io.IOException; +import java.io.Writer; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * JSONWriter provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONWriter can produce one JSON text. + *

+ * A JSONWriter instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting a cascade style. For example,

+ * new JSONWriter(myWriter)
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject();
which writes
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONWriter adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2011-11-24 + */ +public class JSONWriter { + private static final int maxdepth = 200; + + /** + * The comma flag determines if a comma should be output before the next + * value. + */ + private boolean comma; + + /** + * The current mode. Values: + * 'a' (array), + * 'd' (done), + * 'i' (initial), + * 'k' (key), + * 'o' (object). + */ + protected char mode; + + /** + * The object/array stack. + */ + private final JSONObject stack[]; + + /** + * The stack top index. A value of 0 indicates that the stack is empty. + */ + private int top; + + /** + * The writer that will receive the output. + */ + protected Writer writer; + + /** + * Make a fresh JSONWriter. It can be used to build one JSON text. + */ + public JSONWriter(Writer w) { + this.comma = false; + this.mode = 'i'; + this.stack = new JSONObject[maxdepth]; + this.top = 0; + this.writer = w; + } + + /** + * Append a value. + * @param string A string value. + * @return this + * @throws JSONException If the value is out of sequence. + */ + private JSONWriter append(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null pointer"); + } + if (this.mode == 'o' || this.mode == 'a') { + try { + if (this.comma && this.mode == 'a') { + this.writer.write(','); + } + this.writer.write(string); + } catch (IOException e) { + throw new JSONException(e); + } + if (this.mode == 'o') { + this.mode = 'k'; + } + this.comma = true; + return this; + } + throw new JSONException("Value out of sequence."); + } + + /** + * Begin appending a new array. All values until the balancing + * endArray will be appended to this array. The + * endArray method must be called to mark the array's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter array() throws JSONException { + if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { + this.push(null); + this.append("["); + this.comma = false; + return this; + } + throw new JSONException("Misplaced array."); + } + + /** + * End something. + * @param mode Mode + * @param c Closing character + * @return this + * @throws JSONException If unbalanced. + */ + private JSONWriter end(char mode, char c) throws JSONException { + if (this.mode != mode) { + throw new JSONException(mode == 'a' + ? "Misplaced endArray." + : "Misplaced endObject."); + } + this.pop(mode); + try { + this.writer.write(c); + } catch (IOException e) { + throw new JSONException(e); + } + this.comma = true; + return this; + } + + /** + * End an array. This method most be called to balance calls to + * array. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endArray() throws JSONException { + return this.end('a', ']'); + } + + /** + * End an object. This method most be called to balance calls to + * object. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endObject() throws JSONException { + return this.end('k', '}'); + } + + /** + * Append a key. The key will be associated with the next value. In an + * object, every value must be preceded by a key. + * @param string A key string. + * @return this + * @throws JSONException If the key is out of place. For example, keys + * do not belong in arrays or if the key is null. + */ + public JSONWriter key(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null key."); + } + if (this.mode == 'k') { + try { + this.stack[this.top - 1].putOnce(string, Boolean.TRUE); + if (this.comma) { + this.writer.write(','); + } + this.writer.write(JSONObject.quote(string)); + this.writer.write(':'); + this.comma = false; + this.mode = 'o'; + return this; + } catch (IOException e) { + throw new JSONException(e); + } + } + throw new JSONException("Misplaced key."); + } + + + /** + * Begin appending a new object. All keys and values until the balancing + * endObject will be appended to this object. The + * endObject method must be called to mark the object's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter object() throws JSONException { + if (this.mode == 'i') { + this.mode = 'o'; + } + if (this.mode == 'o' || this.mode == 'a') { + this.append("{"); + this.push(new JSONObject()); + this.comma = false; + return this; + } + throw new JSONException("Misplaced object."); + + } + + + /** + * Pop an array or object scope. + * @param c The scope to close. + * @throws JSONException If nesting is wrong. + */ + private void pop(char c) throws JSONException { + if (this.top <= 0) { + throw new JSONException("Nesting error."); + } + char m = this.stack[this.top - 1] == null ? 'a' : 'k'; + if (m != c) { + throw new JSONException("Nesting error."); + } + this.top -= 1; + this.mode = this.top == 0 + ? 'd' + : this.stack[this.top - 1] == null + ? 'a' + : 'k'; + } + + /** + * Push an array or object scope. + * @param c The scope to open. + * @throws JSONException If nesting is too deep. + */ + private void push(JSONObject jo) throws JSONException { + if (this.top >= maxdepth) { + throw new JSONException("Nesting too deep."); + } + this.stack[this.top] = jo; + this.mode = jo == null ? 'a' : 'k'; + this.top += 1; + } + + + /** + * Append either the value true or the value + * false. + * @param b A boolean. + * @return this + * @throws JSONException + */ + public JSONWriter value(boolean b) throws JSONException { + return this.append(b ? "true" : "false"); + } + + /** + * Append a double value. + * @param d A double. + * @return this + * @throws JSONException If the number is not finite. + */ + public JSONWriter value(double d) throws JSONException { + return this.value(new Double(d)); + } + + /** + * Append a long value. + * @param l A long. + * @return this + * @throws JSONException + */ + public JSONWriter value(long l) throws JSONException { + return this.append(Long.toString(l)); + } + + + /** + * Append an object value. + * @param object The object to append. It can be null, or a Boolean, Number, + * String, JSONObject, or JSONArray, or an object that implements JSONString. + * @return this + * @throws JSONException If the value is out of sequence. + */ + public JSONWriter value(Object object) throws JSONException { + return this.append(JSONObject.valueToString(object)); + } +} diff --git a/dot/org/json/XML.java b/dot/org/json/XML.java new file mode 100755 index 0000000..82455b3 --- /dev/null +++ b/dot/org/json/XML.java @@ -0,0 +1,508 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.util.Iterator; + + +/** + * This provides static methods to convert an XML text into a JSONObject, + * and to covert a JSONObject into an XML text. + * @author JSON.org + * @version 2011-02-11 + */ +public class XML { + + /** The Character '&'. */ + public static final Character AMP = new Character('&'); + + /** The Character '''. */ + public static final Character APOS = new Character('\''); + + /** The Character '!'. */ + public static final Character BANG = new Character('!'); + + /** The Character '='. */ + public static final Character EQ = new Character('='); + + /** The Character '>'. */ + public static final Character GT = new Character('>'); + + /** The Character '<'. */ + public static final Character LT = new Character('<'); + + /** The Character '?'. */ + public static final Character QUEST = new Character('?'); + + /** The Character '"'. */ + public static final Character QUOT = new Character('"'); + + /** The Character '/'. */ + public static final Character SLASH = new Character('/'); + + /** + * Replace special characters with XML escapes: + *

+     * & (ampersand) is replaced by &amp;
+     * < (less than) is replaced by &lt;
+     * > (greater than) is replaced by &gt;
+     * " (double quote) is replaced by &quot;
+     * 
+ * @param string The string to be escaped. + * @return The escaped string. + */ + public static String escape(String string) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, length = string.length(); i < length; i++) { + char c = string.charAt(i); + switch (c) { + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '"': + sb.append("""); + break; + case '\'': + sb.append("'"); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + + /** + * Throw an exception if the string contains whitespace. + * Whitespace is not allowed in tagNames and attributes. + * @param string + * @throws JSONException + */ + public static void noSpace(String string) throws JSONException { + int i, length = string.length(); + if (length == 0) { + throw new JSONException("Empty string."); + } + for (i = 0; i < length; i += 1) { + if (Character.isWhitespace(string.charAt(i))) { + throw new JSONException("'" + string + + "' contains a space character."); + } + } + } + + /** + * Scan the content following the named tag, attaching it to the context. + * @param x The XMLTokener containing the source string. + * @param context The JSONObject that will include the new material. + * @param name The tag name. + * @return true if the close tag is processed. + * @throws JSONException + */ + private static boolean parse(XMLTokener x, JSONObject context, + String name) throws JSONException { + char c; + int i; + JSONObject jsonobject = null; + String string; + String tagName; + Object token; + +// Test for and skip past these forms: +// +// +// +// +// Report errors for these forms: +// <> +// <= +// << + + token = x.nextToken(); + +// "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate("content", string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + +// "); + return false; + } else if (token == SLASH) { + +// Close tag + + } else if (token == SLASH) { + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped tag"); + } + if (jsonobject.length() > 0) { + context.accumulate(tagName, jsonobject); + } else { + context.accumulate(tagName, ""); + } + return false; + +// Content, between <...> and + + } else if (token == GT) { + for (;;) { + token = x.nextContent(); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String)token; + if (string.length() > 0) { + jsonobject.accumulate("content", + XML.stringToValue(string)); + } + +// Nested element + + } else if (token == LT) { + if (parse(x, jsonobject, tagName)) { + if (jsonobject.length() == 0) { + context.accumulate(tagName, ""); + } else if (jsonobject.length() == 1 && + jsonobject.opt("content") != null) { + context.accumulate(tagName, + jsonobject.opt("content")); + } else { + context.accumulate(tagName, jsonobject); + } + return false; + } + } + } + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. This is much less ambitious than + * JSONObject.stringToValue, especially because it does not attempt to + * convert plus forms, octal forms, hex forms, or E forms lacking decimal + * points. + * @param string A String. + * @return A simple JSON value. + */ + public static Object stringToValue(String string) { + if ("".equals(string)) { + return string; + } + if ("true".equalsIgnoreCase(string)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(string)) { + return Boolean.FALSE; + } + if ("null".equalsIgnoreCase(string)) { + return JSONObject.NULL; + } + if ("0".equals(string)) { + return new Integer(0); + } + +// If it might be a number, try converting it. If that doesn't work, +// return the string. + + try { + char initial = string.charAt(0); + boolean negative = false; + if (initial == '-') { + initial = string.charAt(1); + negative = true; + } + if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') { + return string; + } + if ((initial >= '0' && initial <= '9')) { + if (string.indexOf('.') >= 0) { + return Double.valueOf(string); + } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) { + Long myLong = new Long(string); + if (myLong.longValue() == myLong.intValue()) { + return new Integer(myLong.intValue()); + } else { + return myLong; + } + } + } + } catch (Exception ignore) { + } + return string; + } + + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation + * because JSON is a data format and XML is a document format. XML uses + * elements, attributes, and content text, while JSON uses unordered + * collections of name/value pairs and arrays of values. JSON does not + * does not like to distinguish between elements and attributes. + * Sequences of similar elements are represented as JSONArrays. Content + * text may be placed in a "content" member. Comments, prologs, DTDs, and + * <[ [ ]]> are ignored. + * @param string The source string. + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONObject toJSONObject(String string) throws JSONException { + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(string); + while (x.more() && x.skipPast("<")) { + parse(x, jo, null); + } + return jo; + } + + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * @param object A JSONObject. + * @return A string. + * @throws JSONException + */ + public static String toString(Object object) throws JSONException { + return toString(object, null); + } + + + /** + * Convert a JSONObject into a well-formed, element-normal XML string. + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @return A string. + * @throws JSONException + */ + public static String toString(Object object, String tagName) + throws JSONException { + StringBuffer sb = new StringBuffer(); + int i; + JSONArray ja; + JSONObject jo; + String key; + Iterator keys; + int length; + String string; + Object value; + if (object instanceof JSONObject) { + +// Emit + + if (tagName != null) { + sb.append('<'); + sb.append(tagName); + sb.append('>'); + } + +// Loop thru the keys. + + jo = (JSONObject)object; + keys = jo.keys(); + while (keys.hasNext()) { + key = keys.next().toString(); + value = jo.opt(key); + if (value == null) { + value = ""; + } + if (value instanceof String) { + string = (String)value; + } else { + string = null; + } + +// Emit content in body + + if ("content".equals(key)) { + if (value instanceof JSONArray) { + ja = (JSONArray)value; + length = ja.length(); + for (i = 0; i < length; i += 1) { + if (i > 0) { + sb.append('\n'); + } + sb.append(escape(ja.get(i).toString())); + } + } else { + sb.append(escape(value.toString())); + } + +// Emit an array of similar keys + + } else if (value instanceof JSONArray) { + ja = (JSONArray)value; + length = ja.length(); + for (i = 0; i < length; i += 1) { + value = ja.get(i); + if (value instanceof JSONArray) { + sb.append('<'); + sb.append(key); + sb.append('>'); + sb.append(toString(value)); + sb.append("'); + } else { + sb.append(toString(value, key)); + } + } + } else if ("".equals(value)) { + sb.append('<'); + sb.append(key); + sb.append("/>"); + +// Emit a new tag + + } else { + sb.append(toString(value, key)); + } + } + if (tagName != null) { + +// Emit the close tag + + sb.append("'); + } + return sb.toString(); + +// XML does not have good support for arrays. If an array appears in a place +// where XML is lacking, synthesize an element. + + } else { + if (object.getClass().isArray()) { + object = new JSONArray(object); + } + if (object instanceof JSONArray) { + ja = (JSONArray)object; + length = ja.length(); + for (i = 0; i < length; i += 1) { + sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); + } + return sb.toString(); + } else { + string = (object == null) ? "null" : escape(object.toString()); + return (tagName == null) ? "\"" + string + "\"" : + (string.length() == 0) ? "<" + tagName + "/>" : + "<" + tagName + ">" + string + ""; + } + } + } +} \ No newline at end of file diff --git a/dot/org/json/XMLTokener.java b/dot/org/json/XMLTokener.java new file mode 100755 index 0000000..07574b0 --- /dev/null +++ b/dot/org/json/XMLTokener.java @@ -0,0 +1,365 @@ +package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * The XMLTokener extends the JSONTokener to provide additional methods + * for the parsing of XML texts. + * @author JSON.org + * @version 2010-12-24 + */ +public class XMLTokener extends JSONTokener { + + + /** The table of entity values. It initially contains Character values for + * amp, apos, gt, lt, quot. + */ + public static final java.util.HashMap entity; + + static { + entity = new java.util.HashMap(8); + entity.put("amp", XML.AMP); + entity.put("apos", XML.APOS); + entity.put("gt", XML.GT); + entity.put("lt", XML.LT); + entity.put("quot", XML.QUOT); + } + + /** + * Construct an XMLTokener from a string. + * @param s A source string. + */ + public XMLTokener(String s) { + super(s); + } + + /** + * Get the text in the CDATA block. + * @return The string up to the ]]>. + * @throws JSONException If the ]]> is not found. + */ + public String nextCDATA() throws JSONException { + char c; + int i; + StringBuffer sb = new StringBuffer(); + for (;;) { + c = next(); + if (end()) { + throw syntaxError("Unclosed CDATA"); + } + sb.append(c); + i = sb.length() - 3; + if (i >= 0 && sb.charAt(i) == ']' && + sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { + sb.setLength(i); + return sb.toString(); + } + } + } + + + /** + * Get the next XML outer token, trimming whitespace. There are two kinds + * of tokens: the '<' character which begins a markup tag, and the content + * text between markup tags. + * + * @return A string, or a '<' Character, or null if there is no more + * source text. + * @throws JSONException + */ + public Object nextContent() throws JSONException { + char c; + StringBuffer sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + if (c == 0) { + return null; + } + if (c == '<') { + return XML.LT; + } + sb = new StringBuffer(); + for (;;) { + if (c == '<' || c == 0) { + back(); + return sb.toString().trim(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + c = next(); + } + } + + + /** + * Return the next entity. These entities are translated to Characters: + * & ' > < ". + * @param ampersand An ampersand character. + * @return A Character or an entity String if the entity is not recognized. + * @throws JSONException If missing ';' in XML entity. + */ + public Object nextEntity(char ampersand) throws JSONException { + StringBuffer sb = new StringBuffer(); + for (;;) { + char c = next(); + if (Character.isLetterOrDigit(c) || c == '#') { + sb.append(Character.toLowerCase(c)); + } else if (c == ';') { + break; + } else { + throw syntaxError("Missing ';' in XML entity: &" + sb); + } + } + String string = sb.toString(); + Object object = entity.get(string); + return object != null ? object : ampersand + string + ";"; + } + + + /** + * Returns the next XML meta token. This is used for skipping over + * and structures. + * @return Syntax characters (< > / = ! ?) are returned as + * Character, and strings and names are returned as Boolean. We don't care + * what the values actually are. + * @throws JSONException If a string is not properly closed or if the XML + * is badly structured. + */ + public Object nextMeta() throws JSONException { + char c; + char q; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped meta tag"); + case '<': + return XML.LT; + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + case '"': + case '\'': + q = c; + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return Boolean.TRUE; + } + } + default: + for (;;) { + c = next(); + if (Character.isWhitespace(c)) { + return Boolean.TRUE; + } + switch (c) { + case 0: + case '<': + case '>': + case '/': + case '=': + case '!': + case '?': + case '"': + case '\'': + back(); + return Boolean.TRUE; + } + } + } + } + + + /** + * Get the next XML Token. These tokens are found inside of angle + * brackets. It may be one of these characters: / > = ! ? or it + * may be a string wrapped in single quotes or double quotes, or it may be a + * name. + * @return a String or a Character. + * @throws JSONException If the XML is not well formed. + */ + public Object nextToken() throws JSONException { + char c; + char q; + StringBuffer sb; + do { + c = next(); + } while (Character.isWhitespace(c)); + switch (c) { + case 0: + throw syntaxError("Misshaped element"); + case '<': + throw syntaxError("Misplaced '<'"); + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + +// Quoted string + + case '"': + case '\'': + q = c; + sb = new StringBuffer(); + for (;;) { + c = next(); + if (c == 0) { + throw syntaxError("Unterminated string"); + } + if (c == q) { + return sb.toString(); + } + if (c == '&') { + sb.append(nextEntity(c)); + } else { + sb.append(c); + } + } + default: + +// Name + + sb = new StringBuffer(); + for (;;) { + sb.append(c); + c = next(); + if (Character.isWhitespace(c)) { + return sb.toString(); + } + switch (c) { + case 0: + return sb.toString(); + case '>': + case '/': + case '=': + case '!': + case '?': + case '[': + case ']': + back(); + return sb.toString(); + case '<': + case '"': + case '\'': + throw syntaxError("Bad character in a name"); + } + } + } + } + + + /** + * Skip characters until past the requested string. + * If it is not found, we are left at the end of the source with a result of false. + * @param to A string to skip past. + * @throws JSONException + */ + public boolean skipPast(String to) throws JSONException { + boolean b; + char c; + int i; + int j; + int offset = 0; + int length = to.length(); + char[] circle = new char[length]; + + /* + * First fill the circle buffer with as many characters as are in the + * to string. If we reach an early end, bail. + */ + + for (i = 0; i < length; i += 1) { + c = next(); + if (c == 0) { + return false; + } + circle[i] = c; + } + /* + * We will loop, possibly for all of the remaining characters. + */ + for (;;) { + j = offset; + b = true; + /* + * Compare the circle buffer with the to string. + */ + for (i = 0; i < length; i += 1) { + if (circle[j] != to.charAt(i)) { + b = false; + break; + } + j += 1; + if (j >= length) { + j -= length; + } + } + /* + * If we exit the loop with b intact, then victory is ours. + */ + if (b) { + return true; + } + /* + * Get the next character. If there isn't one, then defeat is ours. + */ + c = next(); + if (c == 0) { + return false; + } + /* + * Shove the character in the circle buffer and advance the + * circle offset. The offset is mod n. + */ + circle[offset] = c; + offset += 1; + if (offset >= length) { + offset -= length; + } + } + } +} diff --git a/dot/tokens b/dot/tokens new file mode 100644 index 0000000..08e0c1a --- /dev/null +++ b/dot/tokens @@ -0,0 +1,126 @@ +[ + {"terminal": "digraph", "line": 1, "col": 1, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZGlncmFwaA=="}, + {"terminal": "identifier", "line": 1, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Rw=="}, + {"terminal": "lbrace", "line": 1, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewoK"}, + {"terminal": "subgraph", "line": 3, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3ViZ3JhcGg="}, + {"terminal": "identifier", "line": 3, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y2x1c3Rlcl8w"}, + {"terminal": "lbrace", "line": 3, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewo="}, + {"terminal": "value_assign_hint", "line": 4, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 4, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, + {"terminal": "assign", "line": 4, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, + {"terminal": "semi", "line": 4, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "value_assign_hint", "line": 5, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 5, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, + {"terminal": "assign", "line": 5, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGlnaHRncmV5"}, + {"terminal": "semi", "line": 5, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "node", "line": 6, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bm9kZQ=="}, + {"terminal": "lsquare", "line": 6, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 6, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, + {"terminal": "assign", "line": 6, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 6, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, + {"terminal": "comma", "line": 6, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LA=="}, + {"terminal": "identifier", "line": 6, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, + {"terminal": "assign", "line": 6, "col": 29, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 6, "col": 30, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "d2hpdGU="}, + {"terminal": "rsquare", "line": 6, "col": 35, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, + {"terminal": "semi", "line": 6, "col": 36, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 7, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 7, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, + {"terminal": "arrow", "line": 7, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 7, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTE="}, + {"terminal": "arrow", "line": 7, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTI="}, + {"terminal": "arrow", "line": 7, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 7, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, + {"terminal": "semi", "line": 7, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "value_assign_hint", "line": 8, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 8, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGFiZWw="}, + {"terminal": "assign", "line": 8, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 8, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "InByb2Nlc3MgIzEi"}, + {"terminal": "semi", "line": 8, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQoK"}, + {"terminal": "subgraph", "line": 11, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3ViZ3JhcGg="}, + {"terminal": "identifier", "line": 11, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y2x1c3Rlcl8x"}, + {"terminal": "lbrace", "line": 11, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewo="}, + {"terminal": "node", "line": 12, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bm9kZQ=="}, + {"terminal": "lsquare", "line": 12, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 12, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, + {"terminal": "assign", "line": 12, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 12, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, + {"terminal": "rsquare", "line": 12, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, + {"terminal": "semi", "line": 12, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 13, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 13, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjA="}, + {"terminal": "arrow", "line": 13, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 13, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjE="}, + {"terminal": "arrow", "line": 13, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjI="}, + {"terminal": "arrow", "line": 13, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 13, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, + {"terminal": "semi", "line": 13, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "value_assign_hint", "line": 14, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 14, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGFiZWw="}, + {"terminal": "assign", "line": 14, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "InByb2Nlc3MgIzIi"}, + {"terminal": "semi", "line": 14, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "value_assign_hint", "line": 15, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 15, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, + {"terminal": "assign", "line": 15, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 15, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ymx1ZQ=="}, + {"terminal": "semi", "line": 15, "col": 5, "resource": "Auto-inserted semi-colon", "source_string": ""}, + {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQo="}, + {"terminal": "edge_stmt_hint", "line": 17, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 17, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, + {"terminal": "arrow", "line": 17, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 17, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, + {"terminal": "semi", "line": 17, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 18, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 18, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, + {"terminal": "arrow", "line": 18, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 18, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjA="}, + {"terminal": "semi", "line": 18, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 19, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 19, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTE="}, + {"terminal": "arrow", "line": 19, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 19, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, + {"terminal": "semi", "line": 19, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 20, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 20, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjI="}, + {"terminal": "arrow", "line": 20, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 20, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, + {"terminal": "semi", "line": 20, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 21, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 21, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, + {"terminal": "arrow", "line": 21, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 21, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, + {"terminal": "semi", "line": 21, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 22, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 22, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, + {"terminal": "arrow", "line": 22, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 22, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, + {"terminal": "semi", "line": 22, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "edge_stmt_hint", "line": 23, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 23, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, + {"terminal": "arrow", "line": 23, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, + {"terminal": "identifier", "line": 23, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, + {"terminal": "semi", "line": 23, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "node_stmt_hint", "line": 25, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 25, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, + {"terminal": "lsquare", "line": 25, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c2hhcGU="}, + {"terminal": "assign", "line": 25, "col": 15, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "TWRpYW1vbmQ="}, + {"terminal": "rsquare", "line": 25, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, + {"terminal": "semi", "line": 25, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "node_stmt_hint", "line": 26, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, + {"terminal": "identifier", "line": 26, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, + {"terminal": "lsquare", "line": 26, "col": 7, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 26, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c2hhcGU="}, + {"terminal": "assign", "line": 26, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "TXNxdWFyZQ=="}, + {"terminal": "rsquare", "line": 26, "col": 21, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, + {"terminal": "semi", "line": 26, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 27, "col": 1, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQo="} +] From 3594d9d63ad4092ace13ebf0540e69130b29c138 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 8 Aug 2012 14:01:14 -0400 Subject: [PATCH 013/140] adding example workflow descriptions --- test/CopyNumberQCAlt.wdl | 41 ++++++++++++--------------- test/CopyNumberQCReport.wdl | 6 ++++ test/MutSig.json | 69 +++++++++++++++++++++++++++++++++++++++++++++ test/MutSig.wdl | 29 +++++++++++++++++++ 4 files changed, 122 insertions(+), 23 deletions(-) create mode 100644 test/CopyNumberQCReport.wdl create mode 100644 test/MutSig.json create mode 100644 test/MutSig.wdl diff --git a/test/CopyNumberQCAlt.wdl b/test/CopyNumberQCAlt.wdl index 498f879..24deb8c 100644 --- a/test/CopyNumberQCAlt.wdl +++ b/test/CopyNumberQCAlt.wdl @@ -1,29 +1,24 @@ composite_task CopyNumberQC { - step LaneBlackList: (lane_blacklist) = LaneBlackList(); - - for ( sample in samples ) { - step MakeLaneList: (sample.lanelist) = MakeLaneList(sample.bam, sample.id, sample.regions); - step RegionCovPerLane: (sample.rcl) = RegionCovPerLane(sample.bam, sample.id, sample.regions); + step { + task: LaneBlackList[version=6] } - step CopyNumberQc: CopyNumberQCReport(samples.lanelist, samples.rcl, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist); -} - -task MakeLaneList(File input_bam, String sample_id) { - output: File("lanelist_${sample_id}.txt"); - action: task("MakeLaneList", version=11); -} - -task RegionCovPerLane(File input_bam, String sample_id, String region_list) { - output: File("sample_${sample_id}.rcl"); - action: task("RegionCovPerLane", version=16); -} + for ( sample in samples ) { + step MakeLaneList_v11 { + task: MakeLaneList[version=11]; + input: sample.bam, sample.id, sample.regions; + output: sample.lanelist; + } -task LaneBackList() { - output: File("LaneBlackList.txt"); - action: task("LaneBlackList", version=6); -} + step RegionCovPerLane_v16 { + task: RegionCovPerLane[version=16]; + input: sample.bam, sample.id, sample.regions; + output: sample.rcl; + } + } -task CopyNumberQcReport(ListFile lanelist, ListFile rcl, String individual_name, FileList region_list, FileList normals_db, File tumor_seg, File normal_seg, File lane_blacklist) { - action: task("CopyNumberQCReport", version=25); + step CopyNumberQC_v25 { + task: CopyNumberQCReport[version=25]; + input: samples.lanelist, samples.rcl, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist; + } } diff --git a/test/CopyNumberQCReport.wdl b/test/CopyNumberQCReport.wdl new file mode 100644 index 0000000..74d0b6e --- /dev/null +++ b/test/CopyNumberQCReport.wdl @@ -0,0 +1,6 @@ +task CopyNumberQCReport { + action: command("python run_matlab.py --with-display fh_CopyNumberQCReport "); + version: "1.4.2"; + description: "does CopyNumberQCReport"; + ... +} diff --git a/test/MutSig.json b/test/MutSig.json new file mode 100644 index 0000000..a1bbfc8 --- /dev/null +++ b/test/MutSig.json @@ -0,0 +1,69 @@ +{ + "composite_task": { + "name": "MutSig", + "steps": [ + { + "task": { + "name": "MutSigPreProcess", + "version": 86 + }, + "input": ["individual_set_id", "maf1", "maf2", "maf3", "maf4", "maflabel1", "maflabel2", "maflabel3", "maflabel4", "wig1", "wig2", "wig3", "wig4", "build", "context65_dir", "build_dir", "num_categories", "target_list", "paramfile"] + "output": [ + { + "type": "File", + "path": "coverage.prepare.txt", + "var": "coverage_prepare_file" + }, + { + "type": "File", + "path": "patients.txt", + "var": "patient_list" + }, + { + "type": "File", + "path": "${individual_set_id}.maf", + "var": "mutation_list" + }, + { + "type": "File", + "path": "mutation_preprocessing_report.txt", + "var": "mutation_preprocessing_report" + } + ], + }, + { + "task": { + "name": "ProcessCoverageForMutSig", + "version": 75 + }, + "input": ["coverage_prepare_file", "patient_list", "mutation_list"], + "output": [ + { + "type": "File", + "path": "coverage.mat", + "var": "coverage_file" + }, + { + "type": "File", + "path": "mutcategs.txt", + "var": "category_file" + } + ] + }, + { + "task": { + "name": "MutSigRun", + "version": 157 + }, + "output": [ + { + "type": "File", + "path": "bargraphs.png", + "var": "graphs" + } + ], + "input": ["individual_set_id", "mutation_list", "coverage_file", "patient_list", "category_file", "gene_list", "build", "geneset_file", "cosmic_file", "refseq_file", "build_dir", "param_file", "mutation_preprocessing_report", "jobcount"] + } + ] + } +} diff --git a/test/MutSig.wdl b/test/MutSig.wdl new file mode 100644 index 0000000..a92ae15 --- /dev/null +++ b/test/MutSig.wdl @@ -0,0 +1,29 @@ +composite_task MutSig { + + step MutSigPreprocess { + task: MutSigPreprocess[version=86]; + input: individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile; + output: File("coverage.prepare.txt") as coverage_prepare_file, + File("patients.txt") as patient_list + File("${individual_set_id}.maf") as mutation_list, + File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; + } + + step ProcessCoverageForMutSig { + task: ProcessCoverageForMutSig[version=75]; + input: coverage_prepare_file, patient_list, mutation_list; + output: File("coverage.mat") as coverage_file, + File("mutcategs.txt") as category_file; + } + + step MutSigRun { + task: MutSigRun[version=157] + input: individual_set_id, mutation_list, coverage_file, patient_list, category_file, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, mutation_preprocessing_report, jobcount; + output: File("bargraphs.png") as graphs; + } + + output { + graphs + } + +} From 621580cd06d337a85f9ec023b226a8bbd860347e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 8 Aug 2012 18:36:21 -0400 Subject: [PATCH 014/140] fixes --- dot/DotParser.java | 902 ++++++++++++++++++++++++--------------------------- dot/Lexer.java | 148 ++++----- dot/TokenStream.java | 2 +- dot/dot.zgr | 4 +- 4 files changed, 499 insertions(+), 557 deletions(-) diff --git a/dot/DotParser.java b/dot/DotParser.java index 041261b..aece7de 100644 --- a/dot/DotParser.java +++ b/dot/DotParser.java @@ -7,59 +7,59 @@ private HashMap expressionParsers; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, 35, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 17, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, 41, 41, -1, -1, -1, -1, -1, -1 }, - { 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1 }, - { 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, 6, -1, 44, -1 }, - { -1, -1, 36, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, 50 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, 5, -1, -1, -1 }, - { -1, 31, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, 30, 30, -1, -1, -1, -1, -1, -1 }, - { -1, 33, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 45, 16, 45, -1, 16, 40, -1, -1, -1, -1, -1, -1, 16, -1, 21, -1, 32, -1, -1 }, - { 42, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, 42, -1, 42, -1 }, - { -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 51, -1, -1, 51, -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, -1, -1, -1, -1 }, - { -1, 38, -1, 38, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 28, 28, 28, -1, 28, 28, -1, -1, -1, 47, -1, -1, 28, -1, 28, -1, 28, -1, -1 }, - { 49, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1, 49, -1, 49, -1 }, - { -1, 24, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 }, - { -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 9, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 44 }, + { -1, -1, -1, 41, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, 6, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 35, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, 35, -1 }, + { -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, 22 }, + { 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 11, 11, 47, -1, -1, 32, -1, -1, 37, -1, -1, -1, -1, 11, 33, -1, 33 }, + { -1, -1, -1, -1, 13, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 51, -1, 51 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1 }, + { -1, -1, 15, 16, 16, 16, -1, -1, 16, -1, -1, 16, -1, -1, -1, -1, 16, 16, -1, 16 }, + { -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1 }, + { -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1 }, + { 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, -1, -1, 26, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, 23, -1, 19, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, 8 }, + { -1, -1, -1, -1, 3, -1, 3, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 4, -1 }, + { 14, 30, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, 30, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 39, -1, 40, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1 }, }; public enum TerminalId { - TERMINAL_DASHDASH(0, "dashdash"), - TERMINAL_LBRACE(1, "lbrace"), - TERMINAL_NODE(2, "node"), - TERMINAL_SUBGRAPH(3, "subgraph"), - TERMINAL_COLON(4, "colon"), - TERMINAL_EDGE(5, "edge"), - TERMINAL_NODE_STMT_HINT(6, "node_stmt_hint"), - TERMINAL_STRICT(7, "strict"), - TERMINAL_RSQUARE(8, "rsquare"), - TERMINAL_IDENTIFIER(9, "identifier"), - TERMINAL_RBRACE(10, "rbrace"), - TERMINAL_LSQUARE(11, "lsquare"), - TERMINAL_DIGRAPH(12, "digraph"), - TERMINAL_GRAPH(13, "graph"), - TERMINAL_COMMA(14, "comma"), - TERMINAL_EDGE_STMT_HINT(15, "edge_stmt_hint"), - TERMINAL_SEMI(16, "semi"), - TERMINAL_VALUE_ASSIGN_HINT(17, "value_assign_hint"), - TERMINAL_ARROW(18, "arrow"), - TERMINAL_ASSIGN(19, "assign"); + TERMINAL_COLON(0, "colon"), + TERMINAL_ARROW(1, "arrow"), + TERMINAL_RBRACE(2, "rbrace"), + TERMINAL_EDGE(3, "edge"), + TERMINAL_GRAPH(4, "graph"), + TERMINAL_EDGE_STMT_HINT(5, "edge_stmt_hint"), + TERMINAL_STRICT(6, "strict"), + TERMINAL_SEMI(7, "semi"), + TERMINAL_NODE_STMT_HINT(8, "node_stmt_hint"), + TERMINAL_DIGRAPH(9, "digraph"), + TERMINAL_COMMA(10, "comma"), + TERMINAL_VALUE_ASSIGN_HINT(11, "value_assign_hint"), + TERMINAL_RSQUARE(12, "rsquare"), + TERMINAL_LSQUARE(13, "lsquare"), + TERMINAL_ASSIGN(14, "assign"), + TERMINAL_IDENTIFIER(15, "identifier"), + TERMINAL_NODE(16, "node"), + TERMINAL_SUBGRAPH(17, "subgraph"), + TERMINAL_DASHDASH(18, "dashdash"), + TERMINAL_LBRACE(19, "lbrace"); private final int id; private final String string; TerminalId(int id, String string) { @@ -113,27 +113,31 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (20 <= terminal && terminal <= 50); } - private ParseTree parse_graph_type() throws SyntaxError { + private ParseTree parse_attr_type() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(20, "graph_type")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_graph_type(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(20, "attr_type")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 35) { + if (rule == 9) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); tree.add(next); return tree; } - else if (rule == 48) { + else if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); + next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); + tree.add(next); + return tree; + } + else if (rule == 25) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); tree.add(next); return tree; } @@ -142,65 +146,50 @@ else if (rule == 48) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_port_sub() throws SyntaxError { + private ParseTree parse_attr_values() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(21, "port_sub")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_port_sub(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(21, "attr_values")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 12) { + if (rule == 42) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("compass_point", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + parameters.put("value", 1); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); - subtree = this.parse__gen10(); + subtree = this.parse__gen6(); tree.add( subtree); return tree; } - else if (rule == 17) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_attr_values() throws SyntaxError { + private ParseTree parse_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "attr_values")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_values(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(22, "attr")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 22) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 1); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + if (rule == 43) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); tree.add(next); - subtree = this.parse__gen6(); + subtree = this.parse__gen4(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -208,59 +197,45 @@ private ParseTree parse_attr_values() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen5")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen5(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen1")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 8) { + if (current.getId() == 19) { return tree; } } if (current == null) { return tree; } - if (rule == 20) { + if (rule == 1) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_attr_values(); - tree.add( subtree); - subtree = this.parse__gen5(); - tree.add( subtree); return tree; } return tree; } - private ParseTree parse_edge_stmt() throws SyntaxError { + private ParseTree parse_attr_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "edge_stmt")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(24, "attr_stmt")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 9) { + if (rule == 41) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("attributes", 3); - parameters.put("edges", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Edg", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); - tree.add(next); - subtree = this.parse_node_or_subgraph(); - tree.add( subtree); - subtree = this.parse__gen7(); + parameters.put("values", 1); + parameters.put("type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); + subtree = this.parse_attr_type(); tree.add( subtree); subtree = this.parse__gen3(); tree.add( subtree); @@ -271,89 +246,54 @@ private ParseTree parse_edge_stmt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_port_compass_pt() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "port_compass_pt")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_port_compass_pt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 3) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; + ParseTree tree = new ParseTree( new NonTerminal(25, "_gen5")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 12) { + return tree; + } } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_graph() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "graph")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_graph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 41) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("strict", 0); - parameters.put("type", 1); - parameters.put("name", 2); - parameters.put("statements", 4); - tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); - subtree = this.parse__gen0(); - tree.add( subtree); - subtree = this.parse_graph_type(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + if (rule == 2) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); - subtree = this.parse__gen2(); + tree.setListSeparator(next); + subtree = this.parse_attr_values(); + tree.add( subtree); + subtree = this.parse__gen5(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_edge_rhs() throws SyntaxError { + private ParseTree parse_node_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "edge_rhs")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_rhs(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "node_stmt")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 14) { + if (rule == 48) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("edge_type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); - subtree = this.parse_edge_op(); + parameters.put("attributes", 2); + parameters.put("id", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); + tree.add(next); + subtree = this.parse_node_id(); tree.add( subtree); - subtree = this.parse_node_or_subgraph(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } @@ -366,20 +306,18 @@ private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen8")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen8(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "_gen8")); tree.setList("mlist"); if ( current != null ) { - if (current.getId() == 11 || current.getId() == 16) { + if (current.getId() == 13 || current.getId() == 7) { return tree; } } if (current == null) { return tree; } - if (rule == 44) { + if (rule == 35) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_edge_rhs(); tree.add( subtree); @@ -389,62 +327,26 @@ private ParseTree parse__gen8() throws SyntaxError { } return tree; } - private ParseTree parse_attr_type() throws SyntaxError { + private ParseTree parse_edge_op() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "attr_type")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_type(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "edge_op")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 10) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); - tree.add(next); - return tree; - } - else if (rule == 27) { + if (rule == 18) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); tree.add(next); return tree; } - else if (rule == 36) { + else if (rule == 28) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_node_id() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "node_id")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_id(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 34) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("port", 1); - tree.setAstTransformation(new AstTransformNodeCreator("NodeId", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); tree.add(next); - subtree = this.parse__gen9(); - tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -452,50 +354,44 @@ private ParseTree parse_node_id() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse__gen11() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen6")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen6(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "_gen11")); tree.setList(null); if ( current != null ) { - if (current.getId() == 14 || current.getId() == 8) { + if (current.getId() == 19) { return tree; } } if (current == null) { return tree; } - if (rule == 50) { + if (rule == 17) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_value_assign(); + subtree = this.parse_subgraph_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_attr() throws SyntaxError { + private ParseTree parse_port_compass_pt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "attr")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "port_compass_pt")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 43) { + if (rule == 21) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); - subtree = this.parse__gen4(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } @@ -504,23 +400,52 @@ private ParseTree parse_attr() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "_gen7")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen7(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList("mlist"); + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "stmt")); + tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 1) { + if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_rhs(); + subtree = this.parse_attr_stmt(); tree.add( subtree); - subtree = this.parse__gen8(); + return tree; + } + else if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_node_stmt(); + tree.add( subtree); + return tree; + } + else if (rule == 33) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_subgraph(); + tree.add( subtree); + return tree; + } + else if (rule == 37) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 3); + parameters.put("key", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + else if (rule == 47) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_edge_stmt(); tree.add( subtree); return tree; } @@ -529,79 +454,101 @@ private ParseTree parse__gen7() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_graph_type() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "_gen3")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen3(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 16) { - return tree; - } - } + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "graph_type")); + tree.setList(null); if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); + tree.add(next); return tree; } - if (rule == 15) { + else if (rule == 13) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); + tree.add(next); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse_node_or_subgraph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "_gen1")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen1(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "node_or_subgraph")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 1) { - return tree; - } - } if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 12) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_node_id(); + tree.add( subtree); return tree; } - if (rule == 11) { + else if (rule == 51) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); + subtree = this.parse_subgraph(); + tree.add( subtree); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse_edge_op() throws SyntaxError { + private ParseTree parse_node_id() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "edge_op")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_edge_op(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "node_id")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); + if (rule == 38) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("port", 1); + tree.setAstTransformation(new AstTransformNodeCreator("NodeId", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); + subtree = this.parse__gen9(); + tree.add( subtree); return tree; } - else if (rule == 26) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_attr_value_assign() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "attr_value_assign")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 5) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } @@ -610,56 +557,52 @@ else if (rule == 26) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "_gen0")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen0(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "_gen2")); + tree.setList("tlist"); if ( current != null ) { - if (current.getId() == 13 || current.getId() == 12) { + if (current.getId() == 2) { return tree; } } if (current == null) { return tree; } - if (rule == 18) { + if (rule == 16) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); + subtree = this.parse_stmt(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); return tree; } return tree; } - private ParseTree parse_subgraph() throws SyntaxError { + private ParseTree parse_edge_rhs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "subgraph")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_subgraph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "edge_rhs")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 33) { + if (rule == 45) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("statements", 2); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); - subtree = this.parse__gen11(); + parameters.put("node", 1); + parameters.put("edge_type", 0); + tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); + subtree = this.parse_edge_op(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse_node_or_subgraph(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -667,54 +610,57 @@ private ParseTree parse_subgraph() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_stmt() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "stmt")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); + tree.setList("mlist"); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 16) { + if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_stmt(); + subtree = this.parse_edge_rhs(); tree.add( subtree); - return tree; - } - else if (rule == 21) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_stmt(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } - else if (rule == 32) { + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_port_sub() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "port_sub")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 46) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 3); - parameters.put("key", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } - else if (rule == 40) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_node_stmt(); - tree.add( subtree); - return tree; - } - else if (rule == 45) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph(); + else if (rule == 49) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("compass_point", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } @@ -723,77 +669,77 @@ else if (rule == 45) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen9")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen9(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen4")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 0 || current.getId() == 16 || current.getId() == 18 || current.getId() == 11) { + if (current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 7) { + if (rule == 26) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_port(); + subtree = this.parse_attr_values(); + tree.add( subtree); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_subgraph_name() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "subgraph_name")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_subgraph_name(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(41, "_gen6")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 10 || current.getId() == 12) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 4) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); - tree.add(next); - subtree = this.parse__gen1(); + if (rule == 19) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr_value_assign(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_attr_stmt() throws SyntaxError { + private ParseTree parse_subgraph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "attr_stmt")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(42, "subgraph")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 51) { + if (rule == 8) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("values", 1); - parameters.put("type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); - subtree = this.parse_attr_type(); + parameters.put("statements", 2); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); + subtree = this.parse__gen11(); tree.add( subtree); - subtree = this.parse__gen3(); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -801,28 +747,37 @@ private ParseTree parse_attr_stmt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_node_or_subgraph() throws SyntaxError { + private ParseTree parse_graph() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "node_or_subgraph")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_or_subgraph(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(43, "graph")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 23) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_node_id(); + if (rule == 3) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("strict", 0); + parameters.put("type", 1); + parameters.put("name", 2); + parameters.put("statements", 4); + tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); + subtree = this.parse__gen0(); tree.add( subtree); - return tree; - } - else if (rule == 38) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph(); + subtree = this.parse_graph_type(); + tree.add( subtree); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -830,34 +785,28 @@ else if (rule == 38) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_port() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "_gen2")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen2(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList("tlist"); - if ( current != null ) { - if (current.getId() == 10) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(44, "port")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 28) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_stmt(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse_port_sub(); tree.add( subtree); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); @@ -865,18 +814,16 @@ private ParseTree parse__gen10() throws SyntaxError { ParseTree subtree; int rule = current != null ? this.table[25][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(45, "_gen10")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen10(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); tree.setList(null); if ( current != null ) { - if (current.getId() == 0 || current.getId() == 16 || current.getId() == 18 || current.getId() == 11) { + if (current.getId() == 7 || current.getId() == 18 || current.getId() == 13 || current.getId() == 1) { return tree; } } if (current == null) { return tree; } - if (rule == 13) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_port_compass_pt(); tree.add( subtree); @@ -884,101 +831,98 @@ private ParseTree parse__gen10() throws SyntaxError { } return tree; } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "_gen11")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen11(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(46, "_gen9")); tree.setList(null); if ( current != null ) { - if (current.getId() == 1) { + if (current.getId() == 18 || current.getId() == 13 || current.getId() == 7 || current.getId() == 1) { return tree; } } if (current == null) { return tree; } - if (rule == 29) { + if (rule == 14) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph_name(); + subtree = this.parse_port(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_attr_value_assign() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "attr_value_assign")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_attr_value_assign(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen3")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 7) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 25) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); + if (rule == 34) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_attr(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_port() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "port")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_port(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(48, "_gen0")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 9 || current.getId() == 4) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 19) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + if (rule == 40) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); tree.add(next); - subtree = this.parse_port_sub(); - tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_node_stmt() throws SyntaxError { + private ParseTree parse_edge_stmt() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "node_stmt")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse_node_stmt(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); + ParseTree tree = new ParseTree( new NonTerminal(49, "edge_stmt")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 46) { + if (rule == 7) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 2); - parameters.put("id", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); + parameters.put("node", 1); + parameters.put("attributes", 3); + parameters.put("edges", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Edge", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); tree.add(next); - subtree = this.parse_node_id(); + subtree = this.parse_node_or_subgraph(); + tree.add( subtree); + subtree = this.parse__gen7(); tree.add( subtree); subtree = this.parse__gen3(); tree.add( subtree); @@ -989,31 +933,27 @@ private ParseTree parse_node_stmt() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse_subgraph_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[30][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen4")); - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - System.out.println(Utility.getIndentString(trace.length-4) + "parse__gen4(): rule="+rule+", current="+current.getTerminalStr() + "["+current.getId()+"] ("+current.getLine() + ", " + current.getColumn() + ")"); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 8) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(50, "subgraph_name")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 0) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_values(); - tree.add( subtree); - subtree = this.parse__gen5(); + if (rule == 29) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } } diff --git a/dot/Lexer.java b/dot/Lexer.java index f57ab2b..d129cd0 100644 --- a/dot/Lexer.java +++ b/dot/Lexer.java @@ -1,25 +1,27 @@ -import java.util.regex.*; -import java.util.concurrent.Callable; -import java.util.ArrayList; -import java.util.List; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; import java.io.FileNotFoundException; -import java.util.Arrays; -import java.nio.*; -import java.nio.charset.*; -import java.nio.channels.*; +import java.io.IOException; +import java.nio.CharBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; class SourceCode { private File source; - private String resource; + private final String resource; private String contents; private int line; private int col; private int nchars; - SourceCode(String source, String resource) { + SourceCode(final String source, final String resource) { this.contents = source; this.resource = resource; this.line = 1; @@ -27,20 +29,20 @@ this.nchars = 0; } - SourceCode(File source) throws IOException { + SourceCode(final File source) throws IOException { this(source, "utf-8", source.getCanonicalPath()); } - SourceCode(File source, String resource) throws IOException { + SourceCode(final File source, final String resource) throws IOException { this(source, "utf-8", resource); } - SourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { - FileChannel channel = new FileInputStream(source).getChannel(); - MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); - Charset cs = Charset.forName(encoding); - CharsetDecoder cd = cs.newDecoder(); - CharBuffer cb = cd.decode(buffer); + SourceCode(final File source, final String encoding, final String resource) throws IOException, FileNotFoundException { + final FileChannel channel = new FileInputStream(source).getChannel(); + final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); + final Charset cs = Charset.forName(encoding); + final CharsetDecoder cd = cs.newDecoder(); + final CharBuffer cb = cd.decode(buffer); this.contents = cb.toString(); this.resource = resource; this.line = 1; @@ -51,9 +53,9 @@ public int getCharactersProcessed() { return this.nchars; } - public void advance(int amount) { - String str = this.contents.substring(0, amount); - for ( byte b : str.getBytes() ) { + public void advance(final int amount) { + final String str = this.contents.substring(0, amount); + for ( final byte b : str.getBytes() ) { if ( b == (byte) '\n' || b == (byte) '\r' ) { this.line++; this.col = 1; @@ -83,46 +85,47 @@ public int getCol() { } class LexerMatch { - private List terminals; + private final List terminals; LexerMatch() { this.terminals = null; } - LexerMatch(List terminals) { this.terminals = terminals; } + LexerMatch(final List terminals) { this.terminals = terminals; } public List getTerminals() { return this.terminals; } - public void append(Terminal terminal) {this.terminals.add(terminal);} + public void append(final Terminal terminal) {this.terminals.add(terminal);} } abstract class TokenMatchCallback implements Callable { protected Terminal terminal; protected LexerState state; - protected void setContext(Terminal terminal, LexerState state) { + protected void setContext(final Terminal terminal, final LexerState state) { this.terminal = terminal; this.state = state; } - public abstract LexerMatch call(); + @Override +public abstract LexerMatch call(); } class TokenLexer { - private Pattern regex; - private DotParser.TerminalId terminal; - private TokenMatchCallback handler; + private final Pattern regex; + private final DotParser.TerminalId terminal; + private final TokenMatchCallback handler; - TokenLexer(Pattern regex, DotParser.TerminalId terminal) { + TokenLexer(final Pattern regex, final DotParser.TerminalId terminal) { this(regex, terminal, null); } - TokenLexer(Pattern regex, DotParser.TerminalId terminal, TokenMatchCallback handler) { + TokenLexer(final Pattern regex, final DotParser.TerminalId terminal, final TokenMatchCallback handler) { this.regex = regex; this.terminal = terminal; this.handler = handler; } - LexerMatch match(SourceCode source, LexerState state) { - Matcher m = this.regex.matcher(source.getString()); - LexerMatch rval = null; + LexerMatch match(final SourceCode source, final LexerState state) { + final Matcher m = this.regex.matcher(source.getString()); + final LexerMatch rval = null; - String code = source.getString().length() > 20 ? source.getString().substring(0, 20) : source.getString(); + final String code = source.getString().length() > 20 ? source.getString().substring(0, 20) : source.getString(); if ( m.find() ) { - String sourceString = m.group(); + final String sourceString = m.group(); Terminal terminal = null; if ( this.terminal != null ) { @@ -135,7 +138,7 @@ LexerMatch match(SourceCode source, LexerState state) { this.handler.setContext(terminal, state); return this.handler.call(); } else { - ArrayList list = new ArrayList(); + final ArrayList list = new ArrayList(); if ( terminal != null ) list.add(terminal); return new LexerMatch(list); @@ -152,7 +155,7 @@ LexerMatch match(SourceCode source, LexerState state) { this.cache = new ArrayList(); this.square_bracket = 0; } - public void add(Terminal terminal) { + public void add(final Terminal terminal) { this.cache.add(terminal); } public List getCache() { @@ -171,9 +174,9 @@ public int square_level() { return this.square_bracket; } - private boolean cache_contains(DotParser.TerminalId input) { + private boolean cache_contains(final DotParser.TerminalId input) { if ( this.cache.size() > 0 ) { - for ( Terminal t : this.cache ) { + for ( final Terminal t : this.cache ) { if ( t.getId() == input.id() ) { return true; } @@ -187,15 +190,7 @@ private boolean cache_contains_edgeop() { } public LexerMatch stmt_end() { - /* - stmt_end) - i) if cache = ['identifier' + 'assign' + 'identifier'], hint = value_assign_hint - ii) if cache contains edgeop, hint = edge_stmt_hint - iii) if cache[0] = 'identifier' and cache does not contain edgeop, hint = node_stmt_hint - iv) if cache[-1] != 'semi', semi = 'semi' - */ - - ArrayList tokens = new ArrayList(); + final ArrayList tokens = new ArrayList(); Terminal hint = null, semi = null; if ( this.cache.size() == 0 ) { @@ -203,23 +198,23 @@ public LexerMatch stmt_end() { } if ( this.cache.size() >= 3 && - this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() && + this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() && this.cache.get(1).getId() == DotParser.TerminalId.TERMINAL_ASSIGN.id() && this.cache.get(2).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { - DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_VALUE_ASSIGN_HINT; + final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_VALUE_ASSIGN_HINT; hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); } else if ( cache_contains_edgeop() ) { - DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_EDGE_STMT_HINT; + final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_EDGE_STMT_HINT; hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); } else if ( this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { - DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_NODE_STMT_HINT; + final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_NODE_STMT_HINT; hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); } if ( this.cache.get(this.cache.size()-1).getId() != DotParser.TerminalId.TERMINAL_SEMI.id() ) { - DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_SEMI; + final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_SEMI; semi = new Terminal( t.id(), t.string(), "", "Auto-inserted semi-colon", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); } @@ -228,7 +223,7 @@ else if ( this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER. } tokens.addAll(this.cache); - + if ( semi != null ) { tokens.add(semi); } @@ -241,31 +236,34 @@ else if ( this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER. public class Lexer { private static class BackslashNewlineCallback extends TokenMatchCallback { /* called on \\[\r\n] */ + @Override public LexerMatch call() { return null; } } private static class RightBraceOrEOFCallback extends TokenMatchCallback { /* called on }[\r\n]* or EOF */ + @Override public LexerMatch call() { if ( this.state.getCache().size() > 0 ) { - LexerMatch match = this.state.stmt_end(); + final LexerMatch match = this.state.stmt_end(); match.append(this.terminal); return match; } else { this.state.add(this.terminal); - LexerMatch match = new LexerMatch(this.state.getCache()); - this.state.clearCache(); - return match; + //LexerMatch match = new LexerMatch(this.state.getCache()); + //this.state.clearCache(); + return null; } } } private static class LeftBraceCallback extends TokenMatchCallback { /* called on {[\r\n]* */ + @Override public LexerMatch call() { if ( this.state.getCache().size() > 0 ) { this.state.add(this.terminal); - LexerMatch match = new LexerMatch(this.state.getCache()); + final LexerMatch match = new LexerMatch(this.state.getCache()); this.state.clearCache(); return match; } @@ -275,6 +273,7 @@ public LexerMatch call() { } private static class NewLineCallback extends TokenMatchCallback { /* called on [\r\n]+ */ + @Override public LexerMatch call() { if ( this.state.square_level() == 0 ) { return this.state.stmt_end(); @@ -285,6 +284,7 @@ public LexerMatch call() { } private static class LeftSquareBracketCallback extends TokenMatchCallback { /* called on \\[ */ + @Override public LexerMatch call() { if ( this.terminal != null ) { this.state.square_inc(); @@ -295,6 +295,7 @@ public LexerMatch call() { } private static class RightSquareBracketCallback extends TokenMatchCallback { /* called on \\] */ + @Override public LexerMatch call() { if ( this.terminal != null ) { this.state.square_dec(); @@ -305,6 +306,7 @@ public LexerMatch call() { } private static class TokenCallback extends TokenMatchCallback { /* Called on all other tokens */ + @Override public LexerMatch call() { if ( this.terminal != null ) { this.state.add(this.terminal); @@ -312,9 +314,9 @@ public LexerMatch call() { return null; } } - public static void main(String[] args) { - ArrayList regex = new ArrayList(); - TokenCallback cb = new TokenCallback(); + public static void main(final String[] args) { + final ArrayList regex = new ArrayList(); + final TokenCallback cb = new TokenCallback(); regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_DIGRAPH, new TokenCallback()) ); regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_GRAPH, new TokenCallback()) ); regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_SUBGRAPH, new TokenCallback()) ); @@ -322,7 +324,7 @@ public static void main(String[] args) { regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_EDGE, new TokenCallback()) ); regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_NODE, new TokenCallback()) ); regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\}[\r\n]*"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceOrEOFCallback()) ); + regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceOrEOFCallback()) ); regex.add( new TokenLexer(Pattern.compile("^\\{[\r\n]*"), DotParser.TerminalId.TERMINAL_LBRACE, new LeftBraceCallback()) ); regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE, new LeftSquareBracketCallback()) ); regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE, new RightSquareBracketCallback()) ); @@ -342,17 +344,17 @@ public static void main(String[] args) { } try { - SourceCode code = new SourceCode(new File(args[0])); - LexerState state = new LexerState(); - ArrayList terminals = new ArrayList(); + final SourceCode code = new SourceCode(new File(args[0])); + final LexerState state = new LexerState(); + final ArrayList terminals = new ArrayList(); int consumed; boolean progress = true; while (progress) { progress = false; consumed = code.getCharactersProcessed(); - for ( TokenLexer lexer : regex ) { - LexerMatch match = lexer.match(code, state); + for ( final TokenLexer lexer : regex ) { + final LexerMatch match = lexer.match(code, state); if (match != null) { terminals.addAll(match.getTerminals()); @@ -365,15 +367,15 @@ public static void main(String[] args) { } } - ArrayList strs = new ArrayList(); - for (Terminal t : terminals) { + final ArrayList strs = new ArrayList(); + for (final Terminal t : terminals) { strs.add(" " + t.toString()); } System.out.println("["); System.out.println( Utility.join(strs, ",\n") ); System.out.println("]"); System.out.flush(); - } catch (IOException e) { + } catch (final IOException e) { System.err.println(e); System.exit(-1); } diff --git a/dot/TokenStream.java b/dot/TokenStream.java index 60dd51e..b50e557 100644 --- a/dot/TokenStream.java +++ b/dot/TokenStream.java @@ -30,7 +30,7 @@ public Terminal expect(int expecting) throws SyntaxError { if (current.getId() != expecting) { Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current : ""); + formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); throw new SyntaxError(formatter.toString()); } Terminal next = advance(); diff --git a/dot/dot.zgr b/dot/dot.zgr index 1b6d88e..6ff6a9a 100644 --- a/dot/dot.zgr +++ b/dot/dot.zgr @@ -2,7 +2,7 @@ "ll1": { "start": "graph", "rules": [ - "graph := optional('strict') + graph_type + optional('identifier') + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' -> Graph(strict=$0, type=$1, name=$2, statements=$4)", + "graph := optional('strict') + graph_type + optional('identifier') + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' + 'semi' -> Graph(strict=$0, type=$1, name=$2, statements=$4)", "graph_type := 'graph' | 'digraph'", "stmt := node_stmt | edge_stmt | attr_stmt | subgraph", "stmt := 'value_assign_hint' + 'identifier' + 'assign' + 'identifier' -> Assign(key=$1, value=$3)", @@ -11,7 +11,7 @@ "attr := 'lsquare' + list(attr_values, 'comma') + 'rsquare' -> $1", "attr_values := 'identifier' + optional(attr_value_assign) -> AttributeValue(key=$0, value=$1)", "attr_value_assign := 'assign' + 'identifier' -> $1", - "edge_stmt := 'edge_stmt_hint' + node_or_subgraph + mlist(edge_rhs, 1) + list(attr) -> Edg(node=$1, edges=$2, attributes=$3)", + "edge_stmt := 'edge_stmt_hint' + node_or_subgraph + mlist(edge_rhs, 1) + list(attr) -> Edge(node=$1, edges=$2, attributes=$3)", "edge_rhs := edge_op + node_or_subgraph -> EdgeDeclaration( edge_type=$0, node=$1 )", "node_or_subgraph := node_id | subgraph", "edge_op := 'arrow' | 'dashdash'", From 7188440bfb3f15147cb46a2a8a8021de0f50a7dc Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 9 Aug 2012 17:01:51 -0400 Subject: [PATCH 015/140] Adding new example files and grammar file to match (untested) --- test/CopyNumberQC.wdl | 44 ++++++++++++++++---------------------------- test/CopyNumberQCAlt.wdl | 24 ------------------------ test/MutSig.wdl | 26 ++++++++++++-------------- test/wdl.zgr | 33 +++++++++++++++------------------ 4 files changed, 43 insertions(+), 84 deletions(-) delete mode 100644 test/CopyNumberQCAlt.wdl diff --git a/test/CopyNumberQC.wdl b/test/CopyNumberQC.wdl index 2e47f2d..6262fb0 100644 --- a/test/CopyNumberQC.wdl +++ b/test/CopyNumberQC.wdl @@ -1,33 +1,21 @@ composite_task CopyNumberQC { - step MakeLaneList_Normal: (normal_rcl) = MakeLaneList( File("normal.bam"), sample_id ); - step MakeLaneList_Tumor: (tumor_rcl) = MakeLaneList( File("tumor.bam"), sample_id ); - step RegionCovPerLane_Normal: (normal_rcl) = RegionCovPerLane(File("normal.bam"), sample_id, region_list); - step RegionCovPerLane_Tumor: (tumor_rcl) = RegionCovPerLane(File("sample.bam"), sample_id, region_list); - step LaneBlackList: (lane_blacklist) = LaneBlackList() - step CopyNumberQC_${sample.id}: (analysis_file, str) = CopyNumberQCReport(tumor_rcl, normal_rcl, individual_name, tumor_lanelist, normal_lanelist, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist); -} - -step MakeLaneList(File input_bam, String sample_id) { - output: File("lanelist.txt"); - action: task("MakeLaneList", version=11); -} + step LaneBlackList[version=6] { + output: File("lane_blacklist.txt") as lane_blacklist; + } -step RegionCovPerLane(File input_bam, String sample_id, String region_list) { - output: File(""); - action: task("RegionCovPerLane", version=16); -} + for ( sample in samples ) { + step MakeLaneList[version=11] as foobar { + input: bam=sample.bam, id=sample.id, regions=sample.regions; + output: File("${sample.id}.lanelist") as sample.lanelist; + } -step LaneBackList() { - output: File("LaneBlackList.txt"); - action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); -} - -step CopyNumberQcReport(File tumor_rcl, File normal_rcl, String individual_name, File tumor_lanelist, File normal_lanelist, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist) { - output: File("dir/analysis.txt"), "static string"; - action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); -} + step RegionCovPerLane[version=16] { + input: bam=sample.bam, id=sample.id, regions=sample.regions; + output: File("${sample.id}.rcl") as sample.rcl; + } + } -step CopyNumberQcReport(ListFile lanelist, ListFile rcl) { - output: File("dir/analysis.txt"), "static string"; - action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); + step CopyNumberQC[version=25] { + input: samples.lanelist, samples.rcl, lane_blacklist; + } } diff --git a/test/CopyNumberQCAlt.wdl b/test/CopyNumberQCAlt.wdl deleted file mode 100644 index 24deb8c..0000000 --- a/test/CopyNumberQCAlt.wdl +++ /dev/null @@ -1,24 +0,0 @@ -composite_task CopyNumberQC { - step { - task: LaneBlackList[version=6] - } - - for ( sample in samples ) { - step MakeLaneList_v11 { - task: MakeLaneList[version=11]; - input: sample.bam, sample.id, sample.regions; - output: sample.lanelist; - } - - step RegionCovPerLane_v16 { - task: RegionCovPerLane[version=16]; - input: sample.bam, sample.id, sample.regions; - output: sample.rcl; - } - } - - step CopyNumberQC_v25 { - task: CopyNumberQCReport[version=25]; - input: samples.lanelist, samples.rcl, region_list, normals_db, tumor_seg, normal_seg, lane_blacklist; - } -} diff --git a/test/MutSig.wdl b/test/MutSig.wdl index a92ae15..73af420 100644 --- a/test/MutSig.wdl +++ b/test/MutSig.wdl @@ -1,29 +1,27 @@ +/* inputs: + * 1) MutSigPreprocess.{individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile} + * 2) ProcessCoverageForMutSig has no variables. All inputs come from prior step. + * 3) MutSigRun.{individual_set_id, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, jobcount} + */ + composite_task MutSig { - step MutSigPreprocess { - task: MutSigPreprocess[version=86]; - input: individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile; + step MutSigPreprocess[verson=86] { output: File("coverage.prepare.txt") as coverage_prepare_file, - File("patients.txt") as patient_list + File("patients.txt") as patient_list, File("${individual_set_id}.maf") as mutation_list, File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; } - step ProcessCoverageForMutSig { - task: ProcessCoverageForMutSig[version=75]; - input: coverage_prepare_file, patient_list, mutation_list; + step ProcessCoverageForMutSig[version=75] { + input: coverage=coverage_prepare_file, patients=patient_list, mutations=mutation_list; output: File("coverage.mat") as coverage_file, File("mutcategs.txt") as category_file; } - step MutSigRun { - task: MutSigRun[version=157] - input: individual_set_id, mutation_list, coverage_file, patient_list, category_file, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, mutation_preprocessing_report, jobcount; + step MutSigRun[version=157] as MutSig { + input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file, mutation_preprocessing_report; output: File("bargraphs.png") as graphs; } - output { - graphs - } - } diff --git a/test/wdl.zgr b/test/wdl.zgr index 90f018b..3d8e285 100644 --- a/test/wdl.zgr +++ b/test/wdl.zgr @@ -3,24 +3,21 @@ "start": "wdl", "rules": [ "wdl := list(wdl_entity)", - "wdl_entity := workflow | step", - "workflow := 'workflow' + 'identifier' + 'lbrace' + workflow_body + 'rbrace' -> Workflow( name=$1, body=$3 )", - "workflow_body := list(workflow_step)", - "workflow_step := 'step' + 'identifier' + 'colon' + workflow_step_output + 'identifier' + workflow_step_input + 'semi' -> WorkflowStep( name=$1, step=$4, input=$5, output=$3 )", - "workflow_step_input := 'lparen' + list(workflow_step_input_param, 'comma') + 'rparen' -> $1", - "workflow_step_input_param := 'string_literal' -> String(val=$0) | 'file' + 'lparen' + 'string_literal' + 'rparen' -> File(path=$2) | 'identifier' -> Variable(name=$0)", - "workflow_step_output := 'lparen' + list(workflow_step_output_param, 'comma') + 'rparen' + 'equals' -> $1 | _empty", - "workflow_step_output_param := 'identifier' -> Output(var=$0)", - "step := 'step' + 'identifier' + 'lparen' + list(step_parameter, 'comma') + 'rparen' + 'lbrace' + step_body + 'rbrace' -> Step(name=$1, parameters=$3, body=$6)", - "step_parameter := 'identifier' + 'colon' + step_parameter_type -> StepInputParameter(name=$0, type=$2)", - "step_parameter_type := 'file' | 'string'", - "step_body := list(step_body_spec)", - "step_body_spec := step_action | step_output", - "step_action := 'action' + 'colon' + step_action_sub + 'semi' -> $2", - "step_action_sub := step_action_command | step_action_scatter_gather", - "step_action_command := 'command' + 'lparen' + 'string_literal' + 'rparen' -> CommandAction( cmd=$2 )", - "step_action_scatter_gather := 'scatter_gather' + 'lparen' + 'identifier' + 'comma' + 'identifier' + 'comma' + 'identifier' + 'rparen' -> ScatterGatherAction(prepare=$2, scatter=$4, gather=$6)", - "step_output := 'output' + 'colon' + list(workflow_step_input_param, 'comma') + 'semi' -> StepOutputParameters( parameters=$2 )" + "wdl_entity := composite_task", + "composite_task := 'composite_task' + 'identifier' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> CompositeTask( name=$1, body=$3 )", + "composite_task_entity := step | for_loop", + "for_loop := 'for' + 'lparen' + 'identifier' + 'in' + 'identifier' + 'rparen' + 'lbrace' + list(step) + 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )", + "step := 'step' + task_identifier + optional(step_name) + 'lbrace' + list(step_attr) + 'rbrace' -> Step( task=$1, name=$2, body=$4 )", + "task_identifier := 'identifier' + optional(task_attrs) -> Task(name=$0, attributes=$1)", + "task_attrs := 'lsquare' + list(task_attr) + 'rsquare' -> $1", + "task_attr := 'identifier' + 'assign' + task_attr_value -> TaskAttribute(key=$0, value=$2)", + "task_attr_value := 'identifier' | 'string' | 'number'", + "step_name := 'as' + 'identifier' -> $1", + "step_attr := step_input_list | step_output_list", + "step_input_list := 'input' + 'colon' + list(step_input, 'comma') + 'semi' -> StepInputList( inputs=$2 )", + "step_input := 'identifier' + 'assign' + 'identifier'", + "step_output_list := 'output' + 'colon' + list(step_output, 'comma') + 'semi' -> StepOutputList( outputs=$2 )", + "step_output := 'file' + 'lparen' + 'string' + 'rparen' + 'as' + 'identifier'" ] } } From 00588494186a6cd2af497bb451e9edab292f40f0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 10:44:25 -0400 Subject: [PATCH 016/140] removing JSON representation of composite_task --- test/MutSig.json | 69 -------------------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 test/MutSig.json diff --git a/test/MutSig.json b/test/MutSig.json deleted file mode 100644 index a1bbfc8..0000000 --- a/test/MutSig.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "composite_task": { - "name": "MutSig", - "steps": [ - { - "task": { - "name": "MutSigPreProcess", - "version": 86 - }, - "input": ["individual_set_id", "maf1", "maf2", "maf3", "maf4", "maflabel1", "maflabel2", "maflabel3", "maflabel4", "wig1", "wig2", "wig3", "wig4", "build", "context65_dir", "build_dir", "num_categories", "target_list", "paramfile"] - "output": [ - { - "type": "File", - "path": "coverage.prepare.txt", - "var": "coverage_prepare_file" - }, - { - "type": "File", - "path": "patients.txt", - "var": "patient_list" - }, - { - "type": "File", - "path": "${individual_set_id}.maf", - "var": "mutation_list" - }, - { - "type": "File", - "path": "mutation_preprocessing_report.txt", - "var": "mutation_preprocessing_report" - } - ], - }, - { - "task": { - "name": "ProcessCoverageForMutSig", - "version": 75 - }, - "input": ["coverage_prepare_file", "patient_list", "mutation_list"], - "output": [ - { - "type": "File", - "path": "coverage.mat", - "var": "coverage_file" - }, - { - "type": "File", - "path": "mutcategs.txt", - "var": "category_file" - } - ] - }, - { - "task": { - "name": "MutSigRun", - "version": 157 - }, - "output": [ - { - "type": "File", - "path": "bargraphs.png", - "var": "graphs" - } - ], - "input": ["individual_set_id", "mutation_list", "coverage_file", "patient_list", "category_file", "gene_list", "build", "geneset_file", "cosmic_file", "refseq_file", "build_dir", "param_file", "mutation_preprocessing_report", "jobcount"] - } - ] - } -} From 9061661b9b6310d594fb6fadd87669b28f27c68a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:01:13 -0400 Subject: [PATCH 017/140] removing class files --- test/org/json/JSONObject$1.class | Bin 199 -> 0 bytes test/org/json/JSONObject$Null.class | Bin 656 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/org/json/JSONObject$1.class delete mode 100644 test/org/json/JSONObject$Null.class diff --git a/test/org/json/JSONObject$1.class b/test/org/json/JSONObject$1.class deleted file mode 100644 index 64c0e8fc984702841f9e103c6212c0616f9c9baa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmX^0Z`VEs1_mPr9(D$Hb_Om+2Cm@z(xT*4x6GVWMh1SbV1GaVq^#8B61}X%vP7VW zYhH3resN}Ax^HSpMt%xA12-dsXns+;epYdQo<2goiXkHd10w^EXI@@vk#kOBadB!f zBZC0Q6#bmUymWntv5XADSTqYL0JSm!9R>o-K*#{(u`sX#X%+@HAjt{DTtGF9Af5mR E00_A(^Z)<= diff --git a/test/org/json/JSONObject$Null.class b/test/org/json/JSONObject$Null.class deleted file mode 100644 index eb7d3742de52026cd9f35e43bb555c3ab6ef82a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmZutJx{_=6g{s6S}IuNL!kJvIPj5(=!h{UBqkb!p~k_jU?s)+s%B?V)vV)m@7Z>fPSZ?uSj1vF}Ef8!+U`^X~x8r%qSbduZ**aZ(-|8VuaJd?CAtf$K`5wF^>v2Fsh&V`%G)CY zi5PnA3u>+U1SRr}i2Nc(|A{|fnJO{JarsaP>qt!nN`%5lPRp}Sk0~*dof1WO;UvPd a`S22QW6xD&2-8GeK@mu)^cO{xVEh6ptae}k From 7a11f898d1dbcb80265f3234c3cadb7fd2620948 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:01:34 -0400 Subject: [PATCH 018/140] test WDL files --- test/CopyNumberQC.wdl | 2 +- test/MutSig.wdl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CopyNumberQC.wdl b/test/CopyNumberQC.wdl index 6262fb0..e4b3c98 100644 --- a/test/CopyNumberQC.wdl +++ b/test/CopyNumberQC.wdl @@ -16,6 +16,6 @@ composite_task CopyNumberQC { } step CopyNumberQC[version=25] { - input: samples.lanelist, samples.rcl, lane_blacklist; + input: lanelist=samples.lanelist, rcl=samples.rcl, lane_blacklist=lane_blacklist; } } diff --git a/test/MutSig.wdl b/test/MutSig.wdl index 73af420..ea7a538 100644 --- a/test/MutSig.wdl +++ b/test/MutSig.wdl @@ -20,7 +20,7 @@ composite_task MutSig { } step MutSigRun[version=157] as MutSig { - input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file, mutation_preprocessing_report; + input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file=category_file, mutation_preprocessing_report=foobar; output: File("bargraphs.png") as graphs; } From e557a0d8dde965db77b11a4dbddc0de00aeb9957 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:01:49 -0400 Subject: [PATCH 019/140] new grammar for a new syntax --- test/wdl.zgr | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/wdl.zgr b/test/wdl.zgr index 3d8e285..f3e0ea2 100644 --- a/test/wdl.zgr +++ b/test/wdl.zgr @@ -15,9 +15,11 @@ "step_name := 'as' + 'identifier' -> $1", "step_attr := step_input_list | step_output_list", "step_input_list := 'input' + 'colon' + list(step_input, 'comma') + 'semi' -> StepInputList( inputs=$2 )", - "step_input := 'identifier' + 'assign' + 'identifier'", + "step_input := 'identifier' + 'assign' + variable -> StepInput(parameter=$0, value=$2)", "step_output_list := 'output' + 'colon' + list(step_output, 'comma') + 'semi' -> StepOutputList( outputs=$2 )", - "step_output := 'file' + 'lparen' + 'string' + 'rparen' + 'as' + 'identifier'" + "step_output := 'file' + 'lparen' + 'string' + 'rparen' + 'as' + variable -> StepFileOutput( file=$2, as=$5 )", + "variable := 'identifier' + optional(variable_member) -> Variable(name=$0, member=$1)", + "variable_member := 'dot' + 'identifier -> $1" ] } } From 32b36e5c0328c117ba3a89dfbb547be5b3059f01 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:02:24 -0400 Subject: [PATCH 020/140] hermes generated parser and new lexer --- test/Lexer.java | 25 +- test/TokenStream.java | 2 +- test/WdlParser.java | 834 ++++++++++++++++++++++++++------------------------ 3 files changed, 447 insertions(+), 414 deletions(-) diff --git a/test/Lexer.java b/test/Lexer.java index 9f12608..3592a28 100644 --- a/test/Lexer.java +++ b/test/Lexer.java @@ -108,25 +108,32 @@ LexerMatch match(SourceCode source) { public class Lexer { public static void main(String[] args) { + // 'as', 'assign', 'colon', 'comma', 'composite_task', 'file', 'for', 'identifier', 'in', 'input', 'lbrace', 'lparen', 'lsquare', 'number', 'output', 'rbrace', 'rparen', 'rsquare', 'semi', 'step', 'string' ArrayList regex = new ArrayList(); - regex.add( new TokenLexer(Pattern.compile("^scatter-gather(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_SCATTER_GATHER) ); - regex.add( new TokenLexer(Pattern.compile("^String(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STRING) ); - regex.add( new TokenLexer(Pattern.compile("^workflow(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_WORKFLOW) ); - regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); + regex.add( new TokenLexer(Pattern.compile("\\/\\*.*?\\*\\/", Pattern.DOTALL), null) ); + regex.add( new TokenLexer(Pattern.compile("//.*"), null) ); + regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_OUTPUT) ); + regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_INPUT) ); regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STEP) ); - regex.add( new TokenLexer(Pattern.compile("^command(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMMAND) ); - regex.add( new TokenLexer(Pattern.compile("^action(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_ACTION) ); + regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); + regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FOR) ); + regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_AS) ); + regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_IN) ); + regex.add( new TokenLexer(Pattern.compile("^\\."), WdlParser.TerminalId.TERMINAL_DOT) ); regex.add( new TokenLexer(Pattern.compile("^,"), WdlParser.TerminalId.TERMINAL_COMMA) ); regex.add( new TokenLexer(Pattern.compile("^:"), WdlParser.TerminalId.TERMINAL_COLON) ); - regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); regex.add( new TokenLexer(Pattern.compile("^;"), WdlParser.TerminalId.TERMINAL_SEMI) ); + regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_ASSIGN) ); + regex.add( new TokenLexer(Pattern.compile("^\\["), WdlParser.TerminalId.TERMINAL_LSQUARE) ); + regex.add( new TokenLexer(Pattern.compile("^\\]"), WdlParser.TerminalId.TERMINAL_RSQUARE) ); regex.add( new TokenLexer(Pattern.compile("^\\{"), WdlParser.TerminalId.TERMINAL_LBRACE) ); - regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_EQUALS) ); + regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); regex.add( new TokenLexer(Pattern.compile("^\\("), WdlParser.TerminalId.TERMINAL_LPAREN) ); regex.add( new TokenLexer(Pattern.compile("^\\)"), WdlParser.TerminalId.TERMINAL_RPAREN) ); - regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING_LITERAL) ); + regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING) ); regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), WdlParser.TerminalId.TERMINAL_IDENTIFIER) ); + regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), WdlParser.TerminalId.TERMINAL_NUMBER) ); regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); if ( args.length < 1 ) { diff --git a/test/TokenStream.java b/test/TokenStream.java index b50e557..60dd51e 100644 --- a/test/TokenStream.java +++ b/test/TokenStream.java @@ -30,7 +30,7 @@ public Terminal expect(int expecting) throws SyntaxError { if (current.getId() != expecting) { Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); + formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current : ""); throw new SyntaxError(formatter.toString()); } Terminal next = advance(); diff --git a/test/WdlParser.java b/test/WdlParser.java index 4bc1812..c00815a 100644 --- a/test/WdlParser.java +++ b/test/WdlParser.java @@ -7,54 +7,60 @@ private HashMap expressionParsers; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1 }, - { -1, -1, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 36, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 26, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 34, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1 }, - { -1, -1, 3, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, 39, -1, -1, -1, -1, 16, -1 }, - { -1, -1, -1, -1, -1, -1, 25, -1, -1, 25, -1, -1, -1, -1, -1, 22, -1, -1 }, - { -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 14, 14, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 35, -1, -1, 35, 20, 20, -1, -1, -1, -1, 20, -1 }, - { -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, 2, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, 30, -1 }, - { -1, -1, -1, 41, 13, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, + { -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1 }, + { -1, -1, -1, 25, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2 }, + { -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 33, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, 29, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, 11, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, 21, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1 }, }; public enum TerminalId { - TERMINAL_LBRACE(0, "lbrace"), - TERMINAL_COLON(1, "colon"), - TERMINAL_STEP(2, "step"), - TERMINAL_RBRACE(3, "rbrace"), - TERMINAL_ACTION(4, "action"), - TERMINAL_WORKFLOW(5, "workflow"), - TERMINAL_RPAREN(6, "rparen"), - TERMINAL_LPAREN(7, "lparen"), - TERMINAL_SCATTER_GATHER(8, "scatter_gather"), - TERMINAL_SEMI(9, "semi"), - TERMINAL_STRING_LITERAL(10, "string_literal"), - TERMINAL_IDENTIFIER(11, "identifier"), - TERMINAL_STRING(12, "string"), - TERMINAL_OUTPUT(13, "output"), - TERMINAL_COMMAND(14, "command"), - TERMINAL_COMMA(15, "comma"), - TERMINAL_FILE(16, "file"), - TERMINAL_EQUALS(17, "equals"); + TERMINAL_LPAREN(0, "lparen"), + TERMINAL_IN(1, "in"), + TERMINAL_INPUT(2, "input"), + TERMINAL_NUMBER(3, "number"), + TERMINAL_COLON(4, "colon"), + TERMINAL_RBRACE(5, "rbrace"), + TERMINAL_COMMA(6, "comma"), + TERMINAL_IDENTIFIER(7, "identifier"), + TERMINAL_AS(8, "as"), + TERMINAL_ASSIGN(9, "assign"), + TERMINAL_DOT(10, "dot"), + TERMINAL_LSQUARE(11, "lsquare"), + TERMINAL_COMPOSITE_TASK(12, "composite_task"), + TERMINAL_FILE(13, "file"), + TERMINAL_FOR(14, "for"), + TERMINAL_LBRACE(15, "lbrace"), + TERMINAL_STEP(16, "step"), + TERMINAL_OUTPUT(17, "output"), + TERMINAL_SEMI(18, "semi"), + TERMINAL_RPAREN(19, "rparen"), + TERMINAL_STRING(20, "string"), + TERMINAL_RSQUARE(21, "rsquare"); private final int id; private final String string; TerminalId(int id, String string) { @@ -97,163 +103,121 @@ public ParseTree parse(TokenStream tokens) throws SyntaxError { return tree; } private boolean isTerminal(TerminalId terminal) { - return (0 <= terminal.id() && terminal.id() <= 17); + return (0 <= terminal.id() && terminal.id() <= 21); } private boolean isNonTerminal(TerminalId terminal) { - return (18 <= terminal.id() && terminal.id() <= 45); + return (22 <= terminal.id() && terminal.id() <= 51); } private boolean isTerminal(int terminal) { - return (0 <= terminal && terminal <= 17); + return (0 <= terminal && terminal <= 21); } private boolean isNonTerminal(int terminal) { - return (18 <= terminal && terminal <= 45); + return (22 <= terminal && terminal <= 51); } - private ParseTree parse_step_action_command() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(18, "step_action_command")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 27) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("cmd", 2); - tree.setAstTransformation(new AstTransformNodeCreator("CommandAction", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMAND.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_workflow_body() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(19, "workflow_body")); + ParseTree tree = new ParseTree( new NonTerminal(22, "_gen3")); tree.setList(null); - if (current == null) { - return tree; - } - if (rule == 33) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen1(); - tree.add( subtree); - return tree; + if ( current != null ) { + if (current.getId() == 15) { + return tree; + } } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_wdl_entity() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(20, "wdl_entity")); - tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_workflow(); - tree.add( subtree); return tree; } - else if (rule == 36) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_workflow_step_output() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(21, "workflow_step_output")); + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen5")); tree.setList(null); if ( current != null ) { - if (current.getId() == 11) { + if (current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 23) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - subtree = this.parse__gen4(); + if (rule == 39) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attrs(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_EQUALS.id()); - tree.add(next); return tree; } return tree; } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "wdl")); - tree.setList(null); + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen0")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == -1) { + return tree; + } + } if (current == null) { return tree; } - if (rule == 26) { + if (rule == 4) { tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_wdl_entity(); + tree.add( subtree); subtree = this.parse__gen0(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_step_action() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "step_action")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 40) { - tree.setAstTransformation(new AstTransformSubstitution(2)); - next = this.tokens.expect(TerminalId.TERMINAL_ACTION.id()); + if (rule == 41) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR.id()); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN.id()); tree.add(next); - subtree = this.parse_step_action_sub(); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen2(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); tree.add(next); return tree; } @@ -262,48 +226,58 @@ private ParseTree parse_step_action() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen1")); + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "_gen2")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 3) { + if (current.getId() == 5) { return tree; } } if (current == null) { return tree; } - if (rule == 34) { + if (rule == 7) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_workflow_step(); + subtree = this.parse_step(); tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_workflow_step_input() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "workflow_step_input")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "step")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 8) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + if (rule == 14) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 4); + parameters.put("task", 1); + parameters.put("name", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse_task_identifier(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + subtree = this.parse__gen3(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen4(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); tree.add(next); return tree; } @@ -312,38 +286,27 @@ private ParseTree parse_workflow_step_input() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_action_scatter_gather() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "step_action_scatter_gather")); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "task_attr")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 4) { + if (rule == 9) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("gather", 6); - parameters.put("scatter", 4); - parameters.put("prepare", 2); - tree.setAstTransformation(new AstTransformNodeCreator("ScatterGatherAction", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_SCATTER_GATHER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); tree.add(next); + subtree = this.parse_task_attr_value(); + tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -351,37 +314,20 @@ private ParseTree parse_step_action_scatter_gather() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_workflow_step() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "workflow_step")); + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "wdl_entity")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 43) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("input", 5); - parameters.put("step", 4); - parameters.put("name", 1); - parameters.put("output", 3); - tree.setAstTransformation(new AstTransformNodeCreator("WorkflowStep", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - subtree = this.parse_workflow_step_output(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - subtree = this.parse_workflow_step_input(); + if (rule == 36) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -389,30 +335,23 @@ private ParseTree parse_workflow_step() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_workflow() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "workflow")); + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "task_attrs")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 31) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Workflow", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_WORKFLOW.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + if (rule == 22) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); tree.add(next); - subtree = this.parse_workflow_body(); + subtree = this.parse__gen6(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); tree.add(next); return tree; } @@ -421,22 +360,31 @@ private ParseTree parse_workflow() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_workflow_step_output_param() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "workflow_step_output_param")); + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "composite_task")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 18) { + if (rule == 19) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("var", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Output", parameters)); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id()); + tree.add(next); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + tree.add(next); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -444,25 +392,25 @@ private ParseTree parse_workflow_step_output_param() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "step_output")); + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "step_output_list")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 6) { + if (rule == 15) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameters", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputParameters", parameters)); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id()); tree.add(next); next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse__gen9(); tree.add( subtree); next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); tree.add(next); @@ -473,25 +421,25 @@ private ParseTree parse_step_output() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_body_spec() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "step_body_spec")); + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "step_attr")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 15) { + if (rule == 23) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_step_input_list(); tree.add( subtree); return tree; } - else if (rule == 19) { + else if (rule == 44) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_action(); + subtree = this.parse_step_output_list(); tree.add( subtree); return tree; } @@ -500,96 +448,108 @@ else if (rule == 19) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "_gen5")); + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "_gen8")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 17) { + if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); tree.setListSeparator(next); - subtree = this.parse_workflow_step_output_param(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "_gen0")); - tree.setList("nlist"); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "variable")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 31) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen11(); + tree.add( subtree); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen11() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "_gen11")); + tree.setList(null); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 18 || current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 3) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); - tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_workflow_step_input_param() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "workflow_step_input_param")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 16) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("path", 2); - tree.setAstTransformation(new AstTransformNodeCreator("File", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + if (rule == 12) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); tree.add(next); return tree; } - else if (rule == 32) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("val", 0); - tree.setAstTransformation(new AstTransformNodeCreator("String", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING_LITERAL.id()); + else if (rule == 16) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); tree.add(next); return tree; } - else if (rule == 39) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + else if (rule == 25) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id()); tree.add(next); return tree; } @@ -598,65 +558,77 @@ else if (rule == 39) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "_gen3")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 9 || current.getId() == 6) { + if (current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 22) { + if (rule == 35) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_workflow_step_input_param(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen6")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 21) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 30) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen6(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "step")); + ParseTree tree = new ParseTree( new NonTerminal(40, "step_input_list")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 21) { + if (rule == 20) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 6); - parameters.put("name", 1); - parameters.put("parameters", 3); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id()); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - subtree = this.parse__gen6(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); tree.add(next); - subtree = this.parse_step_body(); + subtree = this.parse__gen7(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); tree.add(next); return tree; } @@ -665,19 +637,55 @@ private ParseTree parse_step() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_body() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step_body")); + ParseTree tree = new ParseTree( new NonTerminal(41, "variable_member")); tree.setList(null); if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 45) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); return tree; } - if (rule == 14) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen8(); + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_step_output() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "step_output")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 32) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id()); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } @@ -686,75 +694,76 @@ private ParseTree parse_step_body() throws SyntaxError { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen2")); - tree.setList("slist"); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen4")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 9 || current.getId() == 6) { + if (current.getId() == 5) { return tree; } } if (current == null) { return tree; } - if (rule == 20) { + if (rule == 33) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_workflow_step_input_param(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen4")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "_gen9")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 42) { + if (rule == 26) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_workflow_step_output_param(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_action_sub() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "step_action_sub")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "step_input")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_action_command(); - tree.add( subtree); - return tree; - } - else if (rule == 28) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_action_scatter_gather(); + if (rule == 3) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } @@ -763,26 +772,26 @@ else if (rule == 28) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse_step_parameter_type() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "step_parameter_type")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "composite_task_entity")); tree.setList(null); if (current == null) { throw new SyntaxError("Error: unexpected end of file"); } - if (rule == 24) { + if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); - tree.add(next); + subtree = this.parse_step(); + tree.add( subtree); return tree; } - else if (rule == 30) { + else if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); - tree.add(next); + subtree = this.parse_for_loop(); + tree.add( subtree); return tree; } Formatter formatter = new Formatter(new StringBuilder(), Locale.US); @@ -790,110 +799,127 @@ else if (rule == 30) { formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "_gen8")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 3) { - return tree; - } - } + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "wdl")); + tree.setList(null); if (current == null) { return tree; } - if (rule == 13) { + if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_body_spec(); + subtree = this.parse__gen0(); tree.add( subtree); - subtree = this.parse__gen8(); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse_task_identifier() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "task_identifier")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 17) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("attributes", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } - return tree; + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen6")); - tree.setList("slist"); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "step_name")); + tree.setList(null); + if (current == null) { + throw new SyntaxError("Error: unexpected end of file"); + } + if (rule == 24) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id()); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.add(next); + return tree; + } + Formatter formatter = new Formatter(new StringBuilder(), Locale.US); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); + throw new SyntaxError(formatter.toString()); + } + private ParseTree parse__gen1() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen1")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 5) { return tree; } } if (current == null) { return tree; } - if (rule == 0) { + if (rule == 21) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_parameter(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen7(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "_gen7")); + int rule = current != null ? this.table[29][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(51, "_gen10")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 5) { + if (rule == 8) { tree.setAstTransformation(new AstTransformSubstitution(0)); next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); tree.add(next); tree.setListSeparator(next); - subtree = this.parse_step_parameter(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen7(); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_parameter() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "step_parameter")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 11) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("type", 2); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputParameter", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - subtree = this.parse_step_parameter_type(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } } From 5547b9308be0288647887b49681f333356c0604a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:48:08 -0400 Subject: [PATCH 021/140] removing old python lexer --- test/Lexer.py | 358 -------------------------- test/ParserCommon.py | 210 --------------- test/ParserMain.py | 49 ---- test/wdl_Parser.py | 708 --------------------------------------------------- 4 files changed, 1325 deletions(-) delete mode 100644 test/Lexer.py delete mode 100644 test/ParserCommon.py delete mode 100644 test/ParserMain.py delete mode 100644 test/wdl_Parser.py diff --git a/test/Lexer.py b/test/Lexer.py deleted file mode 100644 index a1d4ad6..0000000 --- a/test/Lexer.py +++ /dev/null @@ -1,358 +0,0 @@ -import re, sys, base64, json -from collections import OrderedDict -from wdl_Parser import wdl_Parser - -def token(string, lineno, colno, terminalId, lexer): - lexer.addToken(Token(terminalId, lexer.resource, wdl_Parser.terminals[terminalId], string, lineno, colno)) - -class SourceCode: - def __init__(self, resource, fp, line = 1, column = 1): - self.__dict__.update(locals()) - self.sourceCode = fp.read() - fp.close() - - def getResource(self): - return self.resource - - def getString(self): - return self.sourceCode - - def getColumn(self): - return self.column - - def getLine(self): - return self.line - - def __str__(self): - return '' % (self.resource) - -class Token: - def __init__(self, id, resource, terminal_str, source_string, lineno, colno): - self.__dict__.update(locals()) - - def getString(self): - return self.source_string - - def getLine(self): - return self.lineno - - def getColumn(self): - return self.colno - - def getId(self): - return self.id - - def getTerminalStr(self): - return self.terminal_str - - def getResource(self): - return self.resource - - def toAst(self): - return self - - def __str__( self ): - return json.dumps(self.json()) - - def json(self): - return OrderedDict([ - ('terminal', self.terminal_str.lower()), - ('line', self.lineno), - ('col', self.colno), - ('resource', self.resource), - ('source_string', base64.b64encode(self.source_string.encode('utf-8')).decode('utf-8')) - ]) - -class Cursor: - def __init__(self): - self.string = '' - self.lineno = 1 - self.colno = 1 - c = lambda x: c_Parser.terminals[x] - self.insertSpaceAfter = { - c('else') - } - - def add(self, token): - if token.lineno > self.lineno: - self.string += ''.join('\n' for i in range(token.lineno - self.lineno)) - self.lineno = token.lineno - self.colno = 1 - if token.colno > self.colno: - self.string += ''.join(' ' for i in range(token.colno - self.colno)) - self.colno = token.colno - self.string += token.source_string - if token.fromPreprocessor or token.id in self.insertSpaceAfter: - self.string += ' ' - self.colno += len(token.source_string) - def __str__(self): - return self.string - -class SourceCodeWriter: - def __init__(self, tokenList, parsetree=None, grammar=None, ast=None, theme=None, highlight=False): - self.__dict__.update(locals()) - self.string = '' - self.lineno = 1 - self.colno = 1 - self.ancestors = dict([(t, set()) for t in self.tokenList]) - self.parents = dict([(t, set()) for t in self.tokenList]) - self.getTokenAncestors(ast) - self.termcolor = XTermColorMap() - c = lambda x: c_Parser.terminals[x] - self.insertSpaceAfter = { - c('else') - } - - # bah, cruft - self.keywords = [] - - def getTokenAncestors(self, ast): - self.stack = [] - self._getTokenAncestors(ast) - - def _getTokenAncestors(self, ast): - if not ast: - return - self.stack.append(ast.name) - for (attr, obj) in ast.attributes.items(): - if isinstance(obj, Token): - self.ancestors[obj] = self.ancestors[obj].union(set(self.stack)) - self.parents[obj] = (self.stack[-1], attr) - elif isinstance(obj, Ast): - self._getTokenAncestors(obj) - elif isinstance(obj, list): - for x in obj: - if isinstance(x, Token): - self.ancestors[x] = self.ancestors[x].union(set(self.stack)) - self.parents[x] = (self.stack[-1], attr) - else: - self._getTokenAncestors(x) - self.stack.pop() - - def add(self, token): - if token.lineno > self.lineno: - self.string += ''.join('\n' for i in range(token.lineno - self.lineno)) - self.lineno = token.lineno - self.colno = 1 - if token.colno > self.colno: - self.string += ''.join(' ' for i in range(token.colno - self.colno)) - self.colno = token.colno - - self.string += self.doHighlight(token) - - if token.fromPreprocessor or token.id in self.insertSpaceAfter: - self.string += ' ' - self.colno += len(token.source_string) - - def doHighlight(self, token): - if not self.highlight: - return token.source_string - - if token in self.parents and len(self.parents[token]): - (parent, attr) = self.parents[token] - if attr == 'declaration_specifiers': - return self.termcolor.colorize(token.source_string, 0x0087ff) - if parent == 'FuncCall' and attr == 'name': - return self.termcolor.colorize(token.source_string, 0x8700ff) - if parent == 'FunctionSignature' and attr == 'declarator': - return self.termcolor.colorize(token.source_string, 0xff8700) - if self.grammar: - if not len(self.keywords): - for rule in self.grammar.getRules(): - terminal = rule.isTokenAlias() - if terminal and rule.nonterminal.string == 'keyword': - self.keywords.append(terminal.string) - if token.terminal_str in self.keywords: - return self.termcolor.colorize(token.source_string, 0xffff00) - if token.terminal_str == 'string_literal': - return self.termcolor.colorize(token.source_string, 0xff0000) - if token.terminal_str == 'identifier': - return self.termcolor.colorize(token.source_string, 0x00ff00) - - return token.source_string - - def __str__(self): - if not len(self.string): - for token in self.tokenList: - self.add(token) - return self.string - -class TokenList(list): - def __init__(self, arg1=[]): - super().__init__(arg1) - self.isIter = False - def __iter__(self): - if self.isIter == False: - self.index = 0 - isIter = True - return self - def __next__(self): - try: - rval = self[self.index] - self.index += 1 - return rval - except: - raise StopIteration - def reset(self): - self.isIter = False - def peek(self, whereto): - try: - return self[self.index + int(whereto)] - except: - return None - def go(self, whereto): - whereto = int(whereto) - if self.index + whereto < 0 or self.index + whereto + 1 > len(self): - raise Exception() - self.index += whereto - return self - def check(self, whereto, ids): - try: - return self[self.index + int(whereto) - 1].id in ids - except: - return False - def toString(self, parsetree=None, grammar=None, ast=None, theme=None, highlight=False): - kwargs = locals() - del kwargs['self'] - scw = SourceCodeWriter(self, **kwargs) - return str(scw) - cursor = Cursor() - for token in self: - cursor.add( token ) - return str(cursor) - -class Lexer: - def __iter__(self): - return self - - def __next__(self): - raise StopIteration() - -class StatelessPatternMatchingLexer(Lexer): - def __init__(self, regex): - self.__dict__.update(locals()) - def match(self, string, wholeStringOnly=False): - for (regex, terminalId, function) in self.regex: - match = regex.match(string) - if match: - sourceString = match.group(0) - if wholeStringOnly and sourceString != string: - continue - return (sourceString, terminalId, function) - return (None, None, None) - -class PatternMatchingLexer(StatelessPatternMatchingLexer): - def __init__(self, sourceCode, regex): - self.__dict__.update(locals()) - self.string = sourceCode.getString() - self.resource = sourceCode.getResource() - self.colno = sourceCode.getColumn() - self.lineno = sourceCode.getLine() - self.cache = [] - - def addToken(self, token): - self.cache.append(token) - - def addTokens(self, tokens): - self.cache.extend(tokens) - - def hasToken(self): - return len(self.cache) > 0 - - def nextToken(self): - if not self.hasToken(): - return None - token = self.cache[0] - self.cache = self.cache[1:] - return token - - def advance(self, string): - self.string = self.string[len(string):] - newlines = len(list(filter(lambda x: x == '\n', string))) - self.lineno += newlines - if newlines > 0: - self.colno = len(string.split('\n')[-1]) + 1 - else: - self.colno += len(string) - - def peek(self, n=1): - # returns an n-item list of tuples: (terminalId, length) - lookahead = list() - loc = 0 - for i in range(n): - current = self.string[loc:] - if not len(current): - return lookahead - for (regex, terminalId, function) in self.regex: - match = regex.match(current) - if match: - length = len(match.group(0)) - loc += length - lookahead.append( (terminalId,match.group(0),) ) - return lookahead - - def nextMatch(self): - activity = True - while activity: - activity = False - if not len(self.string): - raise StopIteration() - (string, terminalId, function) = self.match(self.string) - if string is not None: - activity = True - lineno = self.lineno - colno = self.colno - self.advance( string ) - if function: - function(string, lineno, colno, terminalId, self) - return self.nextToken() - return None - - def __iter__(self): - return self - - def __next__(self): - if self.hasToken(): - token = self.nextToken() - return token - if len(self.string.strip()) <= 0: - raise StopIteration() - token = self.nextMatch() - if not token: - error = 'Invalid character on line %d, col %d' % (self.lineno, self.colno) - raise Exception(error) - return token - -class wdlLexer(PatternMatchingLexer): - regex = [ - ( re.compile(r'scatter-gather(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_SCATTER_GATHER, token ), - ( re.compile(r'String(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_STRING, token ), - ( re.compile(r'workflow(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_WORKFLOW, token ), - ( re.compile(r'File(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_FILE, token ), - ( re.compile(r'output(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_OUTPUT, token ), - ( re.compile(r'step(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_STEP, token ), - ( re.compile(r'command(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_COMMAND, token ), - ( re.compile(r'action(?=[^a-zA-Z_]|$)'), wdl_Parser.TERMINAL_ACTION, token ), - ( re.compile(r','), wdl_Parser.TERMINAL_COMMA, token ), - ( re.compile(r':'), wdl_Parser.TERMINAL_COLON, token ), - ( re.compile(r'}'), wdl_Parser.TERMINAL_RBRACE, token ), - ( re.compile(r';'), wdl_Parser.TERMINAL_SEMI, token ), - ( re.compile(r'{'), wdl_Parser.TERMINAL_LBRACE, token ), - ( re.compile(r'='), wdl_Parser.TERMINAL_EQUALS, token ), - ( re.compile(r'\('), wdl_Parser.TERMINAL_LPAREN, token ), - ( re.compile(r'\)'), wdl_Parser.TERMINAL_RPAREN, token ), - ( re.compile(r'"([^\\\"\n]|\\[\\"\'nrbtfav\?]|\\[0-7]{1,3}|\\x[0-9a-fA-F]+|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"'), wdl_Parser.TERMINAL_STRING_LITERAL, token ), - ( re.compile(r'([a-zA-Z_]|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*'), wdl_Parser.TERMINAL_IDENTIFIER, token ), - ( re.compile(r'[ \t\n]+', 0), None, None ) - ] - - def __init__(self): - super(wdlLexer, self).__init__(SourceCode('/dev/stdin', sys.stdin), self.regex) - -if __name__ == '__main__': - lex = wdlLexer() - tokens = list(lex) - print('[') - for (i, token) in enumerate(tokens): - print(' {}{}'.format(token, ',' if i != len(tokens) - 1 else '')) - print(']') diff --git a/test/ParserCommon.py b/test/ParserCommon.py deleted file mode 100644 index c194523..0000000 --- a/test/ParserCommon.py +++ /dev/null @@ -1,210 +0,0 @@ -import json, base64 -from collections import OrderedDict -class Terminal: - def __init__(self, id, str, base64_source_string, resource, line, col): - self.__dict__.update(locals()) - def getId(self): - return self.id - def toAst(self): - return self - def __str__( self ): - return json.dumps(self.json()) - def json(self): - return OrderedDict([ - ('terminal', self.str.lower()), - ('line', self.line), - ('col', self.col), - ('resource', self.resource), - ('source_string', self.base64_source_string) - ]) - def __str__(self): - return json.dumps(self.json()) -class NonTerminal(): - def __init__(self, id, str): - self.__dict__.update(locals()) - self.list = False - def __str__(self): - return self.str -class AstTransform: - pass -class AstTransformSubstitution(AstTransform): - def __init__(self, idx): - self.__dict__.update(locals()) - def __repr__(self): - return '$' + str(self.idx) - def __str__(self): - return self.__repr__() -class AstTransformNodeCreator(AstTransform): - def __init__( self, name, parameters ): - self.__dict__.update(locals()) - def __repr__( self ): - return self.name + '( ' + ', '.join(['%s=$%s' % (k,str(v)) for k,v in self.parameters.items()]) + ' )' - def __str__(self): - return self.__repr__() -class AstList(list): - def toAst(self): - retval = [] - for ast in self: - retval.append(ast.toAst()) - return retval -class ParseTree(): - def __init__(self, nonterminal): - self.__dict__.update(locals()) - self.children = [] - self.astTransform = None - self.isExpr = False - self.isNud = False - self.isPrefix = False - self.isInfix = False - self.nudMorphemeCount = 0 - self.isExprNud = False # true for rules like _expr := {_expr} + {...} - self.listSeparator = None - self.list = False - def add( self, tree ): - self.children.append( tree ) - def toAst( self ): - if self.list == 'slist' or self.list == 'nlist': - if len(self.children) == 0: - return AstList() - offset = 1 if self.children[0] == self.listSeparator else 0 - r = AstList([self.children[offset].toAst()]) - r.extend(self.children[offset+1].toAst()) - return r - elif self.list == 'tlist': - if len(self.children) == 0: - return AstList() - r = AstList([self.children[0].toAst()]) - r.extend(self.children[2].toAst()) - return r - elif self.list == 'mlist': - r = AstList() - if len(self.children) == 0: - return r - lastElement = len(self.children) - 1 - for i in range(lastElement): - r.append(self.children[i].toAst()) - r.extend(self.children[lastElement].toAst()) - return r - elif self.isExpr: - if isinstance(self.astTransform, AstTransformSubstitution): - return self.children[self.astTransform.idx].toAst() - elif isinstance(self.astTransform, AstTransformNodeCreator): - parameters = {} - for name, idx in self.astTransform.parameters.items(): - if idx == '$': - child = self.children[0] - elif isinstance(self.children[0], ParseTree) and \ - self.children[0].isNud and \ - not self.children[0].isPrefix and \ - not self.isExprNud and \ - not self.isInfix: - if idx < self.children[0].nudMorphemeCount: - child = self.children[0].children[idx] - else: - index = idx - self.children[0].nudMorphemeCount + 1 - child = self.children[index] - elif len(self.children) == 1 and not isinstance(self.children[0], ParseTree) and not isinstance(self.children[0], list): - return self.children[0] - else: - child = self.children[idx] - parameters[name] = child.toAst() - return Ast(self.astTransform.name, parameters) - else: - if isinstance(self.astTransform, AstTransformSubstitution): - return self.children[self.astTransform.idx].toAst() - elif isinstance(self.astTransform, AstTransformNodeCreator): - parameters = {name: self.children[idx].toAst() for name, idx in self.astTransform.parameters.items()} - return Ast(self.astTransform.name, parameters) - elif len(self.children): - return self.children[0].toAst() - else: - return None - def __str__( self ): - children = [] - for child in self.children: - if isinstance(child, list): - children.append('[' + ', '.join([str(a) for a in child]) + ']') - else: - children.append(str(child)) - return '(' + str(self.nonterminal) + ': ' + ', '.join(children) + ')' -class Ast(): - def __init__(self, name, attributes): - self.__dict__.update(locals()) - def getAttr(self, attr): - return self.attributes[attr] - def __str__(self): - return '(%s: %s)' % (self.name, ', '.join('%s=%s'%(str(k), '[' + ', '.join([str(x) for x in v]) + ']' if isinstance(v, list) else str(v) ) for k,v in self.attributes.items())) -def noColor(string, color): - return string -def termColor(string, intcolor): - return "\033[38;5;%dm%s\033[0m" % (intcolor, string) -class AstPrettyPrintable: - def __init__(self, ast, color=False): - self.__dict__.update(locals()) - def getAttr(self, attr): - return self.ast.getAttr(attr) - def __str__(self): - return self._prettyPrint(self.ast, 0) - def _prettyPrint(self, ast, indent = 0): - indentStr = ''.join([' ' for x in range(indent)]) - colored = noColor - if self.color: - colored = termColor - if isinstance(ast, Ast): - string = '%s(%s:\n' % (indentStr, colored(ast.name, 12)) - string += ',\n'.join([ \ - '%s %s=%s' % (indentStr, colored(name, 10), self._prettyPrint(value, indent + 2).lstrip()) for name, value in ast.attributes.items() \ - ]) - string += '\n%s)' % (indentStr) - return string - elif isinstance(ast, list): - if len(ast) == 0: - return '%s[]' % (indentStr) - string = '%s[\n' % (indentStr) - string += ',\n'.join([self._prettyPrint(element, indent + 2) for element in ast]) - string += '\n%s]' % (indentStr) - return string - elif isinstance(ast, Terminal): - return '%s%s' % (indentStr, colored(str(ast), 9)) - else: - return '%s%s' % (indentStr, colored(str(ast), 9)) -class ParseTreePrettyPrintable: - def __init__(self, ast, color=False): - self.__dict__.update(locals()) - def __str__(self): - return self._prettyPrint(self.ast, 0) - def _prettyPrint(self, parsetree, indent = 0): - colored = noColor - if self.color: - colored = termColor - indentStr = ''.join([' ' for x in range(indent)]) - if isinstance(parsetree, ParseTree): - if len(parsetree.children) == 0: - return '(%s: )' % (colored(parsetree.nonterminal, 10)) - string = '%s(%s:\n' % (indentStr, colored(parsetree.nonterminal, 10)) - string += ',\n'.join([ \ - '%s %s' % (indentStr, self._prettyPrint(value, indent + 2).lstrip()) for value in parsetree.children \ - ]) - string += '\n%s)' % (indentStr) - return string - elif isinstance(parsetree, Terminal): - return '%s%s' % (indentStr, colored(str(parsetree), 9)) - else: - return '%s%s' % (indentStr, colored(parsetree, 9)) -class SyntaxError(Exception): - def __init__(self, message): - self.__dict__.update(locals()) - def __str__(self): - return self.message -class TokenStream(list): - def __init__(self, arg): - super().__init__(arg) - self.index = 0 - def advance(self): - self.index += 1 - return self.current() - def current(self): - try: - return self[self.index] - except IndexError: - return None diff --git a/test/ParserMain.py b/test/ParserMain.py deleted file mode 100644 index 696ee62..0000000 --- a/test/ParserMain.py +++ /dev/null @@ -1,49 +0,0 @@ -import sys, json, traceback, base64 -from ParserCommon import * -from wdl_Parser import wdl_Parser -def getParser(name): - if name == 'wdl': - return wdl_Parser() - raise Exception('Invalid grammar name: {}'.format(name)) -if __name__ == '__main__': - grammars = "wdl" - if len(sys.argv) < 2: - print("Usage: {} <{}> ".format(sys.argv[0], grammars)) - sys.exit(-1) - grammar = sys.argv[1].lower() - parser = getParser(grammar) - in_tokens = json.loads(sys.stdin.read()) - tokens = [] - for token in in_tokens: - - for key in ["terminal", "line", "col", "resource", "source_string"]: - if key not in token.keys(): - raise Exception('Malformed token (missing key {0}): {1}'.format(key, json.dumps(token))) - - try: - tokens.append(Terminal( - parser.terminals[token['terminal']], - token['terminal'], - token['source_string'], - token['resource'], - token['line'], - token['col'] - )) - except AttributeError as error: - sys.stderr.write( str(error) + "\n" ) - sys.exit(-1) - - tokens = TokenStream(tokens) - - try: - parsetree = parser.parse( tokens ) - if len(sys.argv) > 2 and sys.argv[2] == 'ast': - ast = parsetree.toAst() - print(AstPrettyPrintable(ast, True)) - else: - print(ParseTreePrettyPrintable(parsetree, True)) - except SyntaxError as error: - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback, file=sys.stdout) - sys.stderr.write( str(error) + "\n" ) - sys.exit(-1) diff --git a/test/wdl_Parser.py b/test/wdl_Parser.py deleted file mode 100644 index 1de0d9b..0000000 --- a/test/wdl_Parser.py +++ /dev/null @@ -1,708 +0,0 @@ -import sys, inspect -from ParserCommon import * -def whoami(): - return inspect.stack()[1][3] -def whosdaddy(): - return inspect.stack()[2][3] -def parse( iterator, entry ): - p = wdl_Parser() - return p.parse(iterator, entry) -class wdl_Parser: - # Quark - finite string set maps one string to exactly one int, and vice versa - terminals = { - 0: 'comma', - 1: 'string_literal', - 2: 'scatter_gather', - 3: 'string', - 4: 'workflow', - 5: 'file', - 6: 'identifier', - 7: 'output', - 8: 'colon', - 9: 'rbrace', - 10: 'semi', - 11: 'step', - 12: 'lbrace', - 13: 'equals', - 14: 'lparen', - 15: 'command', - 16: 'action', - 17: 'rparen', - 'comma': 0, - 'string_literal': 1, - 'scatter_gather': 2, - 'string': 3, - 'workflow': 4, - 'file': 5, - 'identifier': 6, - 'output': 7, - 'colon': 8, - 'rbrace': 9, - 'semi': 10, - 'step': 11, - 'lbrace': 12, - 'equals': 13, - 'lparen': 14, - 'command': 15, - 'action': 16, - 'rparen': 17, - } - # Quark - finite string set maps one string to exactly one int, and vice versa - nonterminals = { - 18: 'step_body', - 19: 'workflow', - 20: 'step', - 21: 'step_body_spec', - 22: '_gen2', - 23: '_gen4', - 24: 'step_action_sub', - 25: 'step_action_scatter_gather', - 26: 'step_parameter_type', - 27: '_gen6', - 28: '_gen5', - 29: '_gen3', - 30: '_gen7', - 31: 'step_action_command', - 32: '_gen8', - 33: 'workflow_body', - 34: '_gen0', - 35: 'workflow_step_output', - 36: 'step_parameter', - 37: 'workflow_step_input', - 38: 'wdl', - 39: 'workflow_step_input_param', - 40: 'workflow_step_output_param', - 41: 'workflow_step', - 42: '_gen1', - 43: 'step_action', - 44: 'wdl_entity', - 45: 'step_output', - 'step_body': 18, - 'workflow': 19, - 'step': 20, - 'step_body_spec': 21, - '_gen2': 22, - '_gen4': 23, - 'step_action_sub': 24, - 'step_action_scatter_gather': 25, - 'step_parameter_type': 26, - '_gen6': 27, - '_gen5': 28, - '_gen3': 29, - '_gen7': 30, - 'step_action_command': 31, - '_gen8': 32, - 'workflow_body': 33, - '_gen0': 34, - 'workflow_step_output': 35, - 'step_parameter': 36, - 'workflow_step_input': 37, - 'wdl': 38, - 'workflow_step_input_param': 39, - 'workflow_step_output_param': 40, - 'workflow_step': 41, - '_gen1': 42, - 'step_action': 43, - 'wdl_entity': 44, - 'step_output': 45, - } - # table[nonterminal][terminal] = rule - table = [ - [-1, -1, -1, -1, -1, -1, -1, 3, -1, 3, -1, -1, -1, -1, -1, -1, 3, -1], - [-1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1], - [-1, 6, -1, -1, -1, 6, 6, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, 39], - [-1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21], - [-1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1], - [-1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, 18, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20], - [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25], - [9, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, 10], - [35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, 24, -1, 43, -1, -1, -1, -1, -1, -1, 24, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, 31, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1], - [-1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1], - [-1, 4, -1, -1, -1, 38, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, 2, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1], - [-1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1], - [-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], - ] - TERMINAL_COMMA = 0 - TERMINAL_STRING_LITERAL = 1 - TERMINAL_SCATTER_GATHER = 2 - TERMINAL_STRING = 3 - TERMINAL_WORKFLOW = 4 - TERMINAL_FILE = 5 - TERMINAL_IDENTIFIER = 6 - TERMINAL_OUTPUT = 7 - TERMINAL_COLON = 8 - TERMINAL_RBRACE = 9 - TERMINAL_SEMI = 10 - TERMINAL_STEP = 11 - TERMINAL_LBRACE = 12 - TERMINAL_EQUALS = 13 - TERMINAL_LPAREN = 14 - TERMINAL_COMMAND = 15 - TERMINAL_ACTION = 16 - TERMINAL_RPAREN = 17 - def __init__(self, tokens=None): - self.__dict__.update(locals()) - self.expressionParsers = dict() - def isTerminal(self, id): - return 0 <= id <= 17 - def isNonTerminal(self, id): - return 18 <= id <= 45 - def parse(self, tokens): - self.tokens = tokens - self.start = 'WDL' - tree = self.parse_wdl() - if self.tokens.current() != None: - raise SyntaxError( 'Finished parsing without consuming all tokens.' ) - return tree - def expect(self, terminalId): - currentToken = self.tokens.current() - if not currentToken: - raise SyntaxError( 'No more tokens. Expecting %s' % (self.terminals[terminalId]) ) - if currentToken.getId() != terminalId: - raise SyntaxError( 'Unexpected symbol when parsing %s. Expected %s, got %s.' %(whosdaddy(), self.terminals[terminalId], currentToken if currentToken else 'None') ) - nextToken = self.tokens.advance() - if nextToken and not self.isTerminal(nextToken.getId()): - raise SyntaxError( 'Invalid symbol ID: %d (%s)' % (nextToken.getId(), nextToken) ) - return currentToken - def parse_step_body(self): - current = self.tokens.current() - rule = self.table[0][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(18, self.nonterminals[18])) - tree.list = False - if current == None: - return tree - if rule == 3: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse__gen8() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_workflow(self): - current = self.tokens.current() - rule = self.table[1][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(19, self.nonterminals[19])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 41: - tree.astTransform = AstTransformNodeCreator('Workflow', {'body': 3, 'name': 1}) - t = self.expect(4) # workflow - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(12) # lbrace - tree.add(t) - subtree = self.parse_workflow_body() - tree.add( subtree ) - t = self.expect(9) # rbrace - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_step(self): - current = self.tokens.current() - rule = self.table[2][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(20, self.nonterminals[20])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 40: - tree.astTransform = AstTransformNodeCreator('Step', {'body': 6, 'name': 1, 'parameters': 3}) - t = self.expect(11) # step - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(14) # lparen - tree.add(t) - subtree = self.parse__gen6() - tree.add( subtree ) - t = self.expect(17) # rparen - tree.add(t) - t = self.expect(12) # lbrace - tree.add(t) - subtree = self.parse_step_body() - tree.add( subtree ) - t = self.expect(9) # rbrace - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_step_body_spec(self): - current = self.tokens.current() - rule = self.table[3][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(21, self.nonterminals[21])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 7: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_action() - tree.add( subtree ) - return tree - elif rule == 17: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_output() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse__gen2(self): - current = self.tokens.current() - rule = self.table[4][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(22, self.nonterminals[22])) - tree.list = 'slist' - if current != None and (current.getId() in [17, 10]): - return tree - if current == None: - return tree - if rule == 6: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_workflow_step_input_param() - tree.add( subtree ) - subtree = self.parse__gen3() - tree.add( subtree ) - return tree - return tree - def parse__gen4(self): - current = self.tokens.current() - rule = self.table[5][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(23, self.nonterminals[23])) - tree.list = 'slist' - if current != None and (current.getId() in [17]): - return tree - if current == None: - return tree - if rule == 1: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_workflow_step_output_param() - tree.add( subtree ) - subtree = self.parse__gen5() - tree.add( subtree ) - return tree - return tree - def parse_step_action_sub(self): - current = self.tokens.current() - rule = self.table[6][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(24, self.nonterminals[24])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 29: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_action_command() - tree.add( subtree ) - return tree - elif rule == 42: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_action_scatter_gather() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_step_action_scatter_gather(self): - current = self.tokens.current() - rule = self.table[7][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(25, self.nonterminals[25])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 36: - tree.astTransform = AstTransformNodeCreator('ScatterGatherAction', {'gather': 6, 'scatter': 4, 'prepare': 2}) - t = self.expect(2) # scatter_gather - tree.add(t) - t = self.expect(14) # lparen - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(0) # comma - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(0) # comma - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(17) # rparen - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_step_parameter_type(self): - current = self.tokens.current() - rule = self.table[8][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(26, self.nonterminals[26])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 18: - tree.astTransform = AstTransformSubstitution(0) - t = self.expect(3) # string - tree.add(t) - return tree - elif rule == 27: - tree.astTransform = AstTransformSubstitution(0) - t = self.expect(5) # file - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse__gen6(self): - current = self.tokens.current() - rule = self.table[9][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(27, self.nonterminals[27])) - tree.list = 'slist' - if current != None and (current.getId() in [17]): - return tree - if current == None: - return tree - if rule == 32: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_parameter() - tree.add( subtree ) - subtree = self.parse__gen7() - tree.add( subtree ) - return tree - return tree - def parse__gen5(self): - current = self.tokens.current() - rule = self.table[10][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(28, self.nonterminals[28])) - tree.list = 'slist' - if current != None and (current.getId() in [17]): - return tree - if current == None: - return tree - if rule == 33: - tree.astTransform = AstTransformSubstitution(0) - t = self.expect(0) # comma - tree.add(t) - tree.listSeparator = t - subtree = self.parse_workflow_step_output_param() - tree.add( subtree ) - subtree = self.parse__gen5() - tree.add( subtree ) - return tree - return tree - def parse__gen3(self): - current = self.tokens.current() - rule = self.table[11][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(29, self.nonterminals[29])) - tree.list = 'slist' - if current != None and (current.getId() in [17, 10]): - return tree - if current == None: - return tree - if rule == 9: - tree.astTransform = AstTransformSubstitution(0) - t = self.expect(0) # comma - tree.add(t) - tree.listSeparator = t - subtree = self.parse_workflow_step_input_param() - tree.add( subtree ) - subtree = self.parse__gen3() - tree.add( subtree ) - return tree - return tree - def parse__gen7(self): - current = self.tokens.current() - rule = self.table[12][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(30, self.nonterminals[30])) - tree.list = 'slist' - if current != None and (current.getId() in [17]): - return tree - if current == None: - return tree - if rule == 35: - tree.astTransform = AstTransformSubstitution(0) - t = self.expect(0) # comma - tree.add(t) - tree.listSeparator = t - subtree = self.parse_step_parameter() - tree.add( subtree ) - subtree = self.parse__gen7() - tree.add( subtree ) - return tree - return tree - def parse_step_action_command(self): - current = self.tokens.current() - rule = self.table[13][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(31, self.nonterminals[31])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 5: - tree.astTransform = AstTransformNodeCreator('CommandAction', {'cmd': 2}) - t = self.expect(15) # command - tree.add(t) - t = self.expect(14) # lparen - tree.add(t) - t = self.expect(1) # string_literal - tree.add(t) - t = self.expect(17) # rparen - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse__gen8(self): - current = self.tokens.current() - rule = self.table[14][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(32, self.nonterminals[32])) - tree.list = 'nlist' - if current != None and (current.getId() in [9]): - return tree - if current == None: - return tree - if rule == 24: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step_body_spec() - tree.add( subtree ) - subtree = self.parse__gen8() - tree.add( subtree ) - return tree - return tree - def parse_workflow_body(self): - current = self.tokens.current() - rule = self.table[15][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(33, self.nonterminals[33])) - tree.list = False - if current == None: - return tree - if rule == 31: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse__gen1() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse__gen0(self): - current = self.tokens.current() - rule = self.table[16][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(34, self.nonterminals[34])) - tree.list = 'nlist' - if current != None and (current.getId() in [-1]): - return tree - if current == None: - return tree - if rule == 23: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_wdl_entity() - tree.add( subtree ) - subtree = self.parse__gen0() - tree.add( subtree ) - return tree - return tree - def parse_workflow_step_output(self): - current = self.tokens.current() - rule = self.table[17][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(35, self.nonterminals[35])) - tree.list = False - if current != None and (current.getId() in [6]): - return tree - if current == None: - return tree - if rule == 11: - tree.astTransform = AstTransformSubstitution(1) - t = self.expect(14) # lparen - tree.add(t) - subtree = self.parse__gen4() - tree.add( subtree ) - t = self.expect(17) # rparen - tree.add(t) - t = self.expect(13) # equals - tree.add(t) - return tree - return tree - def parse_step_parameter(self): - current = self.tokens.current() - rule = self.table[18][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(36, self.nonterminals[36])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 12: - tree.astTransform = AstTransformNodeCreator('StepInputParameter', {'type': 2, 'name': 0}) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(8) # colon - tree.add(t) - subtree = self.parse_step_parameter_type() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_workflow_step_input(self): - current = self.tokens.current() - rule = self.table[19][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(37, self.nonterminals[37])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 14: - tree.astTransform = AstTransformSubstitution(1) - t = self.expect(14) # lparen - tree.add(t) - subtree = self.parse__gen2() - tree.add( subtree ) - t = self.expect(17) # rparen - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_wdl(self): - current = self.tokens.current() - rule = self.table[20][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(38, self.nonterminals[38])) - tree.list = False - if current == None: - return tree - if rule == 34: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse__gen0() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_workflow_step_input_param(self): - current = self.tokens.current() - rule = self.table[21][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(39, self.nonterminals[39])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 4: - tree.astTransform = AstTransformNodeCreator('String', {'val': 0}) - t = self.expect(1) # string_literal - tree.add(t) - return tree - elif rule == 15: - tree.astTransform = AstTransformNodeCreator('Variable', {'name': 0}) - t = self.expect(6) # identifier - tree.add(t) - return tree - elif rule == 38: - tree.astTransform = AstTransformNodeCreator('File', {'path': 2}) - t = self.expect(5) # file - tree.add(t) - t = self.expect(14) # lparen - tree.add(t) - t = self.expect(1) # string_literal - tree.add(t) - t = self.expect(17) # rparen - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_workflow_step_output_param(self): - current = self.tokens.current() - rule = self.table[22][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(40, self.nonterminals[40])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 26: - tree.astTransform = AstTransformNodeCreator('Output', {'var': 0}) - t = self.expect(6) # identifier - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_workflow_step(self): - current = self.tokens.current() - rule = self.table[23][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(41, self.nonterminals[41])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 8: - tree.astTransform = AstTransformNodeCreator('WorkflowStep', {'input': 5, 'step': 4, 'name': 1, 'output': 3}) - t = self.expect(11) # step - tree.add(t) - t = self.expect(6) # identifier - tree.add(t) - t = self.expect(8) # colon - tree.add(t) - subtree = self.parse_workflow_step_output() - tree.add( subtree ) - t = self.expect(6) # identifier - tree.add(t) - subtree = self.parse_workflow_step_input() - tree.add( subtree ) - t = self.expect(10) # semi - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse__gen1(self): - current = self.tokens.current() - rule = self.table[24][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(42, self.nonterminals[42])) - tree.list = 'nlist' - if current != None and (current.getId() in [9]): - return tree - if current == None: - return tree - if rule == 2: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_workflow_step() - tree.add( subtree ) - subtree = self.parse__gen1() - tree.add( subtree ) - return tree - return tree - def parse_step_action(self): - current = self.tokens.current() - rule = self.table[25][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(43, self.nonterminals[43])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 30: - tree.astTransform = AstTransformSubstitution(2) - t = self.expect(16) # action - tree.add(t) - t = self.expect(8) # colon - tree.add(t) - subtree = self.parse_step_action_sub() - tree.add( subtree ) - t = self.expect(10) # semi - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_wdl_entity(self): - current = self.tokens.current() - rule = self.table[26][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(44, self.nonterminals[44])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 0: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_step() - tree.add( subtree ) - return tree - elif rule == 16: - tree.astTransform = AstTransformSubstitution(0) - subtree = self.parse_workflow() - tree.add( subtree ) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) - def parse_step_output(self): - current = self.tokens.current() - rule = self.table[27][current.getId()] if current else -1 - tree = ParseTree( NonTerminal(45, self.nonterminals[45])) - tree.list = False - if current == None: - raise SyntaxError('Error: unexpected end of file') - if rule == 19: - tree.astTransform = AstTransformNodeCreator('StepOutputParameters', {'parameters': 2}) - t = self.expect(7) # output - tree.add(t) - t = self.expect(8) # colon - tree.add(t) - subtree = self.parse__gen2() - tree.add( subtree ) - t = self.expect(10) # semi - tree.add(t) - return tree - raise SyntaxError('Error: Unexpected symbol (%s) when parsing %s' % (current, whoami())) From 2de7e9229187facaffa5720b1a8b48837c002b38 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:48:29 -0400 Subject: [PATCH 022/140] rename test->wdl --- {test => wdl}/1.wdl | 0 {test => wdl}/2.wdl | 0 {test => wdl}/3.wdl | 0 {test => wdl}/Ast.java | 0 {test => wdl}/AstList.java | 0 {test => wdl}/AstNode.java | 0 {test => wdl}/AstTransform.java | 0 {test => wdl}/AstTransformNodeCreator.java | 0 {test => wdl}/AstTransformSubstitution.java | 0 {test => wdl}/CopyNumberQC.wdl | 0 {test => wdl}/CopyNumberQCReport.wdl | 0 {test => wdl}/ExpressionParser.java | 0 {test => wdl}/Lexer.java | 0 {test => wdl}/MutSig.wdl | 0 {test => wdl}/NonTerminal.java | 0 {test => wdl}/ParseTree.java | 0 {test => wdl}/ParseTreeNode.java | 0 {test => wdl}/Parser.java | 0 {test => wdl}/ParserMain.java | 0 {test => wdl}/SyntaxError.java | 0 {test => wdl}/Terminal.java | 0 {test => wdl}/TerminalMap.java | 0 {test => wdl}/TokenStream.java | 0 {test => wdl}/Utility.java | 0 {test => wdl}/WdlParser.java | 0 {test => wdl}/org/json/CDL.java | 0 {test => wdl}/org/json/Cookie.java | 0 {test => wdl}/org/json/CookieList.java | 0 {test => wdl}/org/json/HTTP.java | 0 {test => wdl}/org/json/HTTPTokener.java | 0 {test => wdl}/org/json/JSONArray.java | 0 {test => wdl}/org/json/JSONException.java | 0 {test => wdl}/org/json/JSONML.java | 0 {test => wdl}/org/json/JSONObject.java | 0 {test => wdl}/org/json/JSONString.java | 0 {test => wdl}/org/json/JSONStringer.java | 0 {test => wdl}/org/json/JSONTokener.java | 0 {test => wdl}/org/json/JSONWriter.java | 0 {test => wdl}/org/json/XML.java | 0 {test => wdl}/org/json/XMLTokener.java | 0 {test => wdl}/test.sh | 0 {test => wdl}/wdl.zgr | 0 42 files changed, 0 insertions(+), 0 deletions(-) rename {test => wdl}/1.wdl (100%) rename {test => wdl}/2.wdl (100%) rename {test => wdl}/3.wdl (100%) rename {test => wdl}/Ast.java (100%) rename {test => wdl}/AstList.java (100%) rename {test => wdl}/AstNode.java (100%) rename {test => wdl}/AstTransform.java (100%) rename {test => wdl}/AstTransformNodeCreator.java (100%) rename {test => wdl}/AstTransformSubstitution.java (100%) rename {test => wdl}/CopyNumberQC.wdl (100%) rename {test => wdl}/CopyNumberQCReport.wdl (100%) rename {test => wdl}/ExpressionParser.java (100%) rename {test => wdl}/Lexer.java (100%) rename {test => wdl}/MutSig.wdl (100%) rename {test => wdl}/NonTerminal.java (100%) rename {test => wdl}/ParseTree.java (100%) rename {test => wdl}/ParseTreeNode.java (100%) rename {test => wdl}/Parser.java (100%) rename {test => wdl}/ParserMain.java (100%) rename {test => wdl}/SyntaxError.java (100%) rename {test => wdl}/Terminal.java (100%) rename {test => wdl}/TerminalMap.java (100%) rename {test => wdl}/TokenStream.java (100%) rename {test => wdl}/Utility.java (100%) rename {test => wdl}/WdlParser.java (100%) rename {test => wdl}/org/json/CDL.java (100%) rename {test => wdl}/org/json/Cookie.java (100%) rename {test => wdl}/org/json/CookieList.java (100%) rename {test => wdl}/org/json/HTTP.java (100%) rename {test => wdl}/org/json/HTTPTokener.java (100%) rename {test => wdl}/org/json/JSONArray.java (100%) rename {test => wdl}/org/json/JSONException.java (100%) rename {test => wdl}/org/json/JSONML.java (100%) rename {test => wdl}/org/json/JSONObject.java (100%) rename {test => wdl}/org/json/JSONString.java (100%) rename {test => wdl}/org/json/JSONStringer.java (100%) rename {test => wdl}/org/json/JSONTokener.java (100%) rename {test => wdl}/org/json/JSONWriter.java (100%) rename {test => wdl}/org/json/XML.java (100%) rename {test => wdl}/org/json/XMLTokener.java (100%) rename {test => wdl}/test.sh (100%) rename {test => wdl}/wdl.zgr (100%) diff --git a/test/1.wdl b/wdl/1.wdl similarity index 100% rename from test/1.wdl rename to wdl/1.wdl diff --git a/test/2.wdl b/wdl/2.wdl similarity index 100% rename from test/2.wdl rename to wdl/2.wdl diff --git a/test/3.wdl b/wdl/3.wdl similarity index 100% rename from test/3.wdl rename to wdl/3.wdl diff --git a/test/Ast.java b/wdl/Ast.java similarity index 100% rename from test/Ast.java rename to wdl/Ast.java diff --git a/test/AstList.java b/wdl/AstList.java similarity index 100% rename from test/AstList.java rename to wdl/AstList.java diff --git a/test/AstNode.java b/wdl/AstNode.java similarity index 100% rename from test/AstNode.java rename to wdl/AstNode.java diff --git a/test/AstTransform.java b/wdl/AstTransform.java similarity index 100% rename from test/AstTransform.java rename to wdl/AstTransform.java diff --git a/test/AstTransformNodeCreator.java b/wdl/AstTransformNodeCreator.java similarity index 100% rename from test/AstTransformNodeCreator.java rename to wdl/AstTransformNodeCreator.java diff --git a/test/AstTransformSubstitution.java b/wdl/AstTransformSubstitution.java similarity index 100% rename from test/AstTransformSubstitution.java rename to wdl/AstTransformSubstitution.java diff --git a/test/CopyNumberQC.wdl b/wdl/CopyNumberQC.wdl similarity index 100% rename from test/CopyNumberQC.wdl rename to wdl/CopyNumberQC.wdl diff --git a/test/CopyNumberQCReport.wdl b/wdl/CopyNumberQCReport.wdl similarity index 100% rename from test/CopyNumberQCReport.wdl rename to wdl/CopyNumberQCReport.wdl diff --git a/test/ExpressionParser.java b/wdl/ExpressionParser.java similarity index 100% rename from test/ExpressionParser.java rename to wdl/ExpressionParser.java diff --git a/test/Lexer.java b/wdl/Lexer.java similarity index 100% rename from test/Lexer.java rename to wdl/Lexer.java diff --git a/test/MutSig.wdl b/wdl/MutSig.wdl similarity index 100% rename from test/MutSig.wdl rename to wdl/MutSig.wdl diff --git a/test/NonTerminal.java b/wdl/NonTerminal.java similarity index 100% rename from test/NonTerminal.java rename to wdl/NonTerminal.java diff --git a/test/ParseTree.java b/wdl/ParseTree.java similarity index 100% rename from test/ParseTree.java rename to wdl/ParseTree.java diff --git a/test/ParseTreeNode.java b/wdl/ParseTreeNode.java similarity index 100% rename from test/ParseTreeNode.java rename to wdl/ParseTreeNode.java diff --git a/test/Parser.java b/wdl/Parser.java similarity index 100% rename from test/Parser.java rename to wdl/Parser.java diff --git a/test/ParserMain.java b/wdl/ParserMain.java similarity index 100% rename from test/ParserMain.java rename to wdl/ParserMain.java diff --git a/test/SyntaxError.java b/wdl/SyntaxError.java similarity index 100% rename from test/SyntaxError.java rename to wdl/SyntaxError.java diff --git a/test/Terminal.java b/wdl/Terminal.java similarity index 100% rename from test/Terminal.java rename to wdl/Terminal.java diff --git a/test/TerminalMap.java b/wdl/TerminalMap.java similarity index 100% rename from test/TerminalMap.java rename to wdl/TerminalMap.java diff --git a/test/TokenStream.java b/wdl/TokenStream.java similarity index 100% rename from test/TokenStream.java rename to wdl/TokenStream.java diff --git a/test/Utility.java b/wdl/Utility.java similarity index 100% rename from test/Utility.java rename to wdl/Utility.java diff --git a/test/WdlParser.java b/wdl/WdlParser.java similarity index 100% rename from test/WdlParser.java rename to wdl/WdlParser.java diff --git a/test/org/json/CDL.java b/wdl/org/json/CDL.java similarity index 100% rename from test/org/json/CDL.java rename to wdl/org/json/CDL.java diff --git a/test/org/json/Cookie.java b/wdl/org/json/Cookie.java similarity index 100% rename from test/org/json/Cookie.java rename to wdl/org/json/Cookie.java diff --git a/test/org/json/CookieList.java b/wdl/org/json/CookieList.java similarity index 100% rename from test/org/json/CookieList.java rename to wdl/org/json/CookieList.java diff --git a/test/org/json/HTTP.java b/wdl/org/json/HTTP.java similarity index 100% rename from test/org/json/HTTP.java rename to wdl/org/json/HTTP.java diff --git a/test/org/json/HTTPTokener.java b/wdl/org/json/HTTPTokener.java similarity index 100% rename from test/org/json/HTTPTokener.java rename to wdl/org/json/HTTPTokener.java diff --git a/test/org/json/JSONArray.java b/wdl/org/json/JSONArray.java similarity index 100% rename from test/org/json/JSONArray.java rename to wdl/org/json/JSONArray.java diff --git a/test/org/json/JSONException.java b/wdl/org/json/JSONException.java similarity index 100% rename from test/org/json/JSONException.java rename to wdl/org/json/JSONException.java diff --git a/test/org/json/JSONML.java b/wdl/org/json/JSONML.java similarity index 100% rename from test/org/json/JSONML.java rename to wdl/org/json/JSONML.java diff --git a/test/org/json/JSONObject.java b/wdl/org/json/JSONObject.java similarity index 100% rename from test/org/json/JSONObject.java rename to wdl/org/json/JSONObject.java diff --git a/test/org/json/JSONString.java b/wdl/org/json/JSONString.java similarity index 100% rename from test/org/json/JSONString.java rename to wdl/org/json/JSONString.java diff --git a/test/org/json/JSONStringer.java b/wdl/org/json/JSONStringer.java similarity index 100% rename from test/org/json/JSONStringer.java rename to wdl/org/json/JSONStringer.java diff --git a/test/org/json/JSONTokener.java b/wdl/org/json/JSONTokener.java similarity index 100% rename from test/org/json/JSONTokener.java rename to wdl/org/json/JSONTokener.java diff --git a/test/org/json/JSONWriter.java b/wdl/org/json/JSONWriter.java similarity index 100% rename from test/org/json/JSONWriter.java rename to wdl/org/json/JSONWriter.java diff --git a/test/org/json/XML.java b/wdl/org/json/XML.java similarity index 100% rename from test/org/json/XML.java rename to wdl/org/json/XML.java diff --git a/test/org/json/XMLTokener.java b/wdl/org/json/XMLTokener.java similarity index 100% rename from test/org/json/XMLTokener.java rename to wdl/org/json/XMLTokener.java diff --git a/test/test.sh b/wdl/test.sh similarity index 100% rename from test/test.sh rename to wdl/test.sh diff --git a/test/wdl.zgr b/wdl/wdl.zgr similarity index 100% rename from test/wdl.zgr rename to wdl/wdl.zgr From 21cea64fb07b2c44fed631f3aff07fb38376f969 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 12:49:56 -0400 Subject: [PATCH 023/140] README -> README.md --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 6a76e8e368bc8921e3c748be92110cc74a7f9ede Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 13:51:30 -0300 Subject: [PATCH 024/140] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 616b35f..b78ac65 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ Workflow Description Language +============================= + +`./dot` - Contains a DOT Language parser +`./wdl` - Contains a WDL parser From f403982f94854fe8edbe93f14311fac856432f89 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 13:51:45 -0300 Subject: [PATCH 025/140] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b78ac65..fe78002 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ Workflow Description Language ============================= -`./dot` - Contains a DOT Language parser -`./wdl` - Contains a WDL parser +* `./dot` - Contains a DOT Language parser +* `./wdl` - Contains a WDL parser From 27e3e2c2c5d13a433317a531a8d2e6c5d5b622af Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 15:16:31 -0400 Subject: [PATCH 026/140] removing test files --- wdl/1.wdl | 1 - wdl/2.wdl | 3 --- wdl/3.wdl | 24 ------------------------ wdl/test.sh | 2 -- 4 files changed, 30 deletions(-) delete mode 100644 wdl/1.wdl delete mode 100644 wdl/2.wdl delete mode 100644 wdl/3.wdl delete mode 100644 wdl/test.sh diff --git a/wdl/1.wdl b/wdl/1.wdl deleted file mode 100644 index 8be4dfc..0000000 --- a/wdl/1.wdl +++ /dev/null @@ -1 +0,0 @@ -workflow name {} diff --git a/wdl/2.wdl b/wdl/2.wdl deleted file mode 100644 index 3ebef1e..0000000 --- a/wdl/2.wdl +++ /dev/null @@ -1,3 +0,0 @@ -workflow name { - step PreprocessNormal: (normal_pp_bam) = PreprocessBam( File("normal.bam"), "xyz" ); -} diff --git a/wdl/3.wdl b/wdl/3.wdl deleted file mode 100644 index 4292246..0000000 --- a/wdl/3.wdl +++ /dev/null @@ -1,24 +0,0 @@ -workflow SomeAnalysisWorkflow { - step PreprocessNormal: (normal_pp_bam) = PreprocessBam( File("normal.bam"), "xyz" ); - step PreprocessTumor: (tumor_pp_bam) = PreprocessBam( File("tumor.bam"), "abc" ); - step DoAnalysis: (analysis_file, str) = DoAnalysis(normal_pp_bam, tumor_pp_bam); - step GenerateReport: GenerateReport(); -} - -step PreprocessBam(input_bam:File, option:String) { - output: File("preprocessed.bam"); - action: command("python ${libdir}preprocess.py ${input_bam} --with-option=${option}"); -} - -step DoAnalysis(normal_bam:File, tumor_bam:File) { - output: File("dir/analysis.txt"), "static string"; - action: command("python ${libdir}script.py ${normal_bam} ${tumor_bam}"); -} - -step GenerateReport() { - action: command("Rscript ${libdir}report.R"); -} - -step ScatterGatherStep() { - action: scatter-gather(prepare, scatter, gather); -} diff --git a/wdl/test.sh b/wdl/test.sh deleted file mode 100644 index 955dfa8..0000000 --- a/wdl/test.sh +++ /dev/null @@ -1,2 +0,0 @@ -cat 1.wdl | python Lexer.py | python ParserMain.py wdl ast -java Lexer 3.wdl > tokens ; cat tokens | java ParserMain wdl ast From e5d2a8760a644516ac62fbeaaf201b421988aa93 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 10 Aug 2012 16:58:01 -0400 Subject: [PATCH 027/140] work in progress --- dot/Lexer.java | 137 +++-- dot/hermes.log | 0 dot/tokens | 126 ----- wdl/Lexer.java | 40 +- wdl/Parser.java | 2 +- wdl/ParserMain.java | 24 +- wdl/README.md | 13 + wdl/SourceCode.java | 10 + wdl/SyntaxErrorFormatter.java | 13 + wdl/TokenStream.java | 16 +- wdl/WdlParser.java | 1112 ++++++++++++++++++++++++----------------- 11 files changed, 823 insertions(+), 670 deletions(-) delete mode 100644 dot/hermes.log delete mode 100644 dot/tokens create mode 100644 wdl/README.md create mode 100644 wdl/SourceCode.java create mode 100644 wdl/SyntaxErrorFormatter.java diff --git a/dot/Lexer.java b/dot/Lexer.java index d129cd0..0eb2c02 100644 --- a/dot/Lexer.java +++ b/dot/Lexer.java @@ -89,7 +89,9 @@ public int getCol() { LexerMatch() { this.terminals = null; } LexerMatch(final List terminals) { this.terminals = terminals; } public List getTerminals() { return this.terminals; } - public void append(final Terminal terminal) {this.terminals.add(terminal);} + public void add(final Terminal terminal) {this.terminals.add(terminal);} + public void addAll(final List terminals) {this.terminals.addAll(terminals);} + public void addAll(final LexerMatch match) {this.terminals.addAll(match.getTerminals());} } abstract class TokenMatchCallback implements Callable { @@ -100,7 +102,7 @@ protected void setContext(final Terminal terminal, final LexerState state) { this.state = state; } @Override -public abstract LexerMatch call(); + public abstract LexerMatch call(); } class TokenLexer { @@ -120,7 +122,6 @@ protected void setContext(final Terminal terminal, final LexerState state) { LexerMatch match(final SourceCode source, final LexerState state) { final Matcher m = this.regex.matcher(source.getString()); - final LexerMatch rval = null; final String code = source.getString().length() > 20 ? source.getString().substring(0, 20) : source.getString(); @@ -144,7 +145,7 @@ LexerMatch match(final SourceCode source, final LexerState state) { return new LexerMatch(list); } } - return rval; + return null; } } @@ -241,13 +242,12 @@ public LexerMatch call() { return null; } } - private static class RightBraceOrEOFCallback extends TokenMatchCallback { - /* called on }[\r\n]* or EOF */ + private static class EofCallback extends TokenMatchCallback { + /* called on ^$ */ @Override public LexerMatch call() { if ( this.state.getCache().size() > 0 ) { final LexerMatch match = this.state.stmt_end(); - match.append(this.terminal); return match; } else { this.state.add(this.terminal); @@ -257,6 +257,22 @@ public LexerMatch call() { } } } + private static class RightBraceCallback extends TokenMatchCallback { + /* called on }[\r\n]* */ + @Override + public LexerMatch call() { + LexerMatch match = null; + if ( this.state.getCache().size() > 0 ) { + match = this.state.stmt_end(); + } else { + //match = new LexerMatch + this.state.add(this.terminal); + //LexerMatch match = new LexerMatch(this.state.getCache()); + //this.state.clearCache(); + } + return null; + } + } private static class LeftBraceCallback extends TokenMatchCallback { /* called on {[\r\n]* */ @Override @@ -314,63 +330,80 @@ public LexerMatch call() { return null; } } - public static void main(final String[] args) { - final ArrayList regex = new ArrayList(); - final TokenCallback cb = new TokenCallback(); - regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_DIGRAPH, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_GRAPH, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_SUBGRAPH, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_STRICT, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_EDGE, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_]|$)"), DotParser.TerminalId.TERMINAL_NODE, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceOrEOFCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\{[\r\n]*"), DotParser.TerminalId.TERMINAL_LBRACE, new LeftBraceCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE, new LeftSquareBracketCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE, new RightSquareBracketCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\\\[\r\n]"), DotParser.TerminalId.TERMINAL_ASSIGN, new BackslashNewlineCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\"|[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?))"), DotParser.TerminalId.TERMINAL_IDENTIFIER, new TokenCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^[\r\n]+"), null, new NewLineCallback()) ); - regex.add( new TokenLexer(Pattern.compile("^\\s+"), null, new TokenCallback()) ); + private ArrayList regex; + + public Lexer() { + this.regex = new ArrayList(); + this.regex.add( new TokenLexer(Pattern.compile("^$"), null, new EofCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_DIGRAPH, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_GRAPH, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_SUBGRAPH, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_STRICT, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_EDGE, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_NODE, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\{[\r\n]*"), DotParser.TerminalId.TERMINAL_LBRACE, new LeftBraceCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE, new LeftSquareBracketCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE, new RightSquareBracketCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\\\[\r\n]"), DotParser.TerminalId.TERMINAL_ASSIGN, new BackslashNewlineCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\"|[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?))"), DotParser.TerminalId.TERMINAL_IDENTIFIER, new TokenCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^[\r\n]+"), null, new NewLineCallback()) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null, new TokenCallback()) ); + } + + private LexerMatch onMatch(Terminal terminal) { + return null; + } + + public List getTokens(SourceCode code) { + final LexerState state = new LexerState(); + final List terminals = new ArrayList(); + int consumed; + boolean progress = true; + + while (progress) { + progress = false; + consumed = code.getCharactersProcessed(); + for ( final TokenLexer lexer : regex ) { + final LexerMatch match = lexer.match(code, state); + + if (match != null) { + terminals.addAll(match.getTerminals()); + } + + if ( consumed < code.getCharactersProcessed() ) { + progress = true; + break; + } + } + } + return terminals; + } + + public static void main(final String[] args) { if ( args.length < 1 ) { System.err.println("Usage: Lexer "); System.exit(-1); } + try { + Lexer lexer = new Lexer(); final SourceCode code = new SourceCode(new File(args[0])); - final LexerState state = new LexerState(); - final ArrayList terminals = new ArrayList(); - int consumed; - boolean progress = true; - - while (progress) { - progress = false; - consumed = code.getCharactersProcessed(); - for ( final TokenLexer lexer : regex ) { - final LexerMatch match = lexer.match(code, state); - - if (match != null) { - terminals.addAll(match.getTerminals()); - } - - if ( consumed < code.getCharactersProcessed() ) { - progress = true; - break; - } - } - } - final ArrayList strs = new ArrayList(); + final List terminals = lexer.getTokens(code); + for (final Terminal t : terminals) { strs.add(" " + t.toString()); } + System.out.println("["); System.out.println( Utility.join(strs, ",\n") ); System.out.println("]"); diff --git a/dot/hermes.log b/dot/hermes.log deleted file mode 100644 index e69de29..0000000 diff --git a/dot/tokens b/dot/tokens deleted file mode 100644 index 08e0c1a..0000000 --- a/dot/tokens +++ /dev/null @@ -1,126 +0,0 @@ -[ - {"terminal": "digraph", "line": 1, "col": 1, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZGlncmFwaA=="}, - {"terminal": "identifier", "line": 1, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Rw=="}, - {"terminal": "lbrace", "line": 1, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewoK"}, - {"terminal": "subgraph", "line": 3, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3ViZ3JhcGg="}, - {"terminal": "identifier", "line": 3, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y2x1c3Rlcl8w"}, - {"terminal": "lbrace", "line": 3, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewo="}, - {"terminal": "value_assign_hint", "line": 4, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 4, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, - {"terminal": "assign", "line": 4, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, - {"terminal": "semi", "line": 4, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "value_assign_hint", "line": 5, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 5, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, - {"terminal": "assign", "line": 5, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGlnaHRncmV5"}, - {"terminal": "semi", "line": 5, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "node", "line": 6, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bm9kZQ=="}, - {"terminal": "lsquare", "line": 6, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 6, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, - {"terminal": "assign", "line": 6, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 6, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, - {"terminal": "comma", "line": 6, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LA=="}, - {"terminal": "identifier", "line": 6, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, - {"terminal": "assign", "line": 6, "col": 29, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 6, "col": 30, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "d2hpdGU="}, - {"terminal": "rsquare", "line": 6, "col": 35, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, - {"terminal": "semi", "line": 6, "col": 36, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 7, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 7, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, - {"terminal": "arrow", "line": 7, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 7, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTE="}, - {"terminal": "arrow", "line": 7, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTI="}, - {"terminal": "arrow", "line": 7, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 7, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, - {"terminal": "semi", "line": 7, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "value_assign_hint", "line": 8, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 8, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGFiZWw="}, - {"terminal": "assign", "line": 8, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 8, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "InByb2Nlc3MgIzEi"}, - {"terminal": "semi", "line": 8, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQoK"}, - {"terminal": "subgraph", "line": 11, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3ViZ3JhcGg="}, - {"terminal": "identifier", "line": 11, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y2x1c3Rlcl8x"}, - {"terminal": "lbrace", "line": 11, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ewo="}, - {"terminal": "node", "line": 12, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bm9kZQ=="}, - {"terminal": "lsquare", "line": 12, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 12, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3R5bGU="}, - {"terminal": "assign", "line": 12, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 12, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZmlsbGVk"}, - {"terminal": "rsquare", "line": 12, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, - {"terminal": "semi", "line": 12, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 13, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 13, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjA="}, - {"terminal": "arrow", "line": 13, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 13, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjE="}, - {"terminal": "arrow", "line": 13, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjI="}, - {"terminal": "arrow", "line": 13, "col": 20, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 13, "col": 23, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, - {"terminal": "semi", "line": 13, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "value_assign_hint", "line": 14, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 14, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "bGFiZWw="}, - {"terminal": "assign", "line": 14, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "InByb2Nlc3MgIzIi"}, - {"terminal": "semi", "line": 14, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "value_assign_hint", "line": 15, "col": 5, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 15, "col": 5, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Y29sb3I="}, - {"terminal": "assign", "line": 15, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 15, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ymx1ZQ=="}, - {"terminal": "semi", "line": 15, "col": 5, "resource": "Auto-inserted semi-colon", "source_string": ""}, - {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQo="}, - {"terminal": "edge_stmt_hint", "line": 17, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 17, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, - {"terminal": "arrow", "line": 17, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 17, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, - {"terminal": "semi", "line": 17, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 18, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 18, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, - {"terminal": "arrow", "line": 18, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 18, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjA="}, - {"terminal": "semi", "line": 18, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 19, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 19, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTE="}, - {"terminal": "arrow", "line": 19, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 19, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, - {"terminal": "semi", "line": 19, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 20, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 20, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjI="}, - {"terminal": "arrow", "line": 20, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 20, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, - {"terminal": "semi", "line": 20, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 21, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 21, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, - {"terminal": "arrow", "line": 21, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 21, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTA="}, - {"terminal": "semi", "line": 21, "col": 11, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 22, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 22, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YTM="}, - {"terminal": "arrow", "line": 22, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 22, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, - {"terminal": "semi", "line": 22, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "edge_stmt_hint", "line": 23, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 23, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "YjM="}, - {"terminal": "arrow", "line": 23, "col": 6, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "LT4="}, - {"terminal": "identifier", "line": 23, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, - {"terminal": "semi", "line": 23, "col": 12, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "node_stmt_hint", "line": 25, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 25, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c3RhcnQ="}, - {"terminal": "lsquare", "line": 25, "col": 9, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 25, "col": 10, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c2hhcGU="}, - {"terminal": "assign", "line": 25, "col": 15, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 16, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "TWRpYW1vbmQ="}, - {"terminal": "rsquare", "line": 25, "col": 24, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, - {"terminal": "semi", "line": 25, "col": 25, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "node_stmt_hint", "line": 26, "col": 3, "resource": "Context-disambiguating token", "source_string": ""}, - {"terminal": "identifier", "line": 26, "col": 3, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "ZW5k"}, - {"terminal": "lsquare", "line": 26, "col": 7, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 26, "col": 8, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "c2hhcGU="}, - {"terminal": "assign", "line": 26, "col": 13, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 14, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "TXNxdWFyZQ=="}, - {"terminal": "rsquare", "line": 26, "col": 21, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "XQ=="}, - {"terminal": "semi", "line": 26, "col": 22, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 27, "col": 1, "resource": "/Users/scott/projects/wdl/dot/2.dot", "source_string": "fQo="} -] diff --git a/wdl/Lexer.java b/wdl/Lexer.java index 3592a28..5d932fa 100644 --- a/wdl/Lexer.java +++ b/wdl/Lexer.java @@ -1,5 +1,6 @@ import java.util.regex.*; import java.util.ArrayList; +import java.util.List; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -9,38 +10,43 @@ import java.nio.charset.*; import java.nio.channels.*; -class SourceCode { +class WdlSourceCode implements SourceCode{ private File source; private String resource; private String contents; private int line; private int col; + private StringBuilder currentLine; + private List lines; - SourceCode(String source, String resource) { - this.contents = source; - this.resource = resource; - this.line = 1; - this.col = 1; + WdlSourceCode(String source, String resource) { + init(source, resource); } - SourceCode(File source) throws IOException { + WdlSourceCode(File source) throws IOException { this(source, "utf-8", source.getCanonicalPath()); } - SourceCode(File source, String resource) throws IOException { + WdlSourceCode(File source, String resource) throws IOException { this(source, "utf-8", resource); } - SourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { + WdlSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { FileChannel channel = new FileInputStream(source).getChannel(); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); Charset cs = Charset.forName(encoding); CharsetDecoder cd = cs.newDecoder(); CharBuffer cb = cd.decode(buffer); - this.contents = cb.toString(); + init(cb.toString(), resource); + } + + private void init(String contents, String resource) { + this.contents = contents; this.resource = resource; this.line = 1; this.col = 1; + this.lines = new ArrayList(); + this.currentLine = new StringBuilder(); } public void advance(int amount) { @@ -68,9 +74,17 @@ public int getLine() { return this.line; } - public int getCol() { + public int getColumn() { return this.col; } + + public String getLine(int lineno) { + return null; // TODO + } + + public List getLines() { + return null; // TODO + } } class LexerMatch { @@ -96,7 +110,7 @@ LexerMatch match(SourceCode source) { String sourceString = m.group(); if (this.terminal != null) - rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol())); + rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getColumn())); else rval = new LexerMatch(); @@ -142,7 +156,7 @@ public static void main(String[] args) { } try { - SourceCode code = new SourceCode(new File(args[0])); + SourceCode code = new WdlSourceCode(new File(args[0])); ArrayList terminal_strings = new ArrayList(); boolean progress = true; diff --git a/wdl/Parser.java b/wdl/Parser.java index 8746412..7b41d6f 100644 --- a/wdl/Parser.java +++ b/wdl/Parser.java @@ -1,4 +1,4 @@ interface Parser { - ParseTree parse(TokenStream tokens) throws SyntaxError; + ParseTree parse(TokenStream tokens, SyntaxErrorFormatter formatter) throws SyntaxError; TerminalMap getTerminalMap(); } diff --git a/wdl/ParserMain.java b/wdl/ParserMain.java index b337817..1350d2b 100644 --- a/wdl/ParserMain.java +++ b/wdl/ParserMain.java @@ -1,6 +1,28 @@ import org.json.*; import java.io.*; +import java.util.List; class ParserMain { + private static class DefaultSyntaxErrorFormatter implements SyntaxErrorFormatter { + private TerminalMap map; + DefaultSyntaxErrorFormatter(TerminalMap map) { + this.map = map; + } + public String unexpected_eof(String method, List expected) { + return "Error: unexpected end of file"; + } + public String excess_tokens(String method, Terminal terminal) { + return "Finished parsing without consuming all tokens"; + } + public String unexpected_symbol(String method, Terminal actual, List expected) { + return "Unexpected symbol (" + actual.getTerminalStr() + ") when parsing " + method; + } + public String no_more_tokens(String method, int expecting) { + return "No more tokens. Expecting " + this.map.get(expecting); + } + public String invalid_terminal(String method, Terminal invalid) { + return "Invalid symbol ID: "+invalid.getId()+" ("+invalid.getTerminalStr()+")"; + } + } private static Parser getParser(String name) throws Exception { if (name.equals("wdl")) { return new WdlParser(); @@ -31,7 +53,7 @@ public static void main(String args[]) { token.getInt("col") )); } - ParseTreeNode parsetree = parser.parse(tokens); + ParseTreeNode parsetree = parser.parse(tokens, new DefaultSyntaxErrorFormatter(terminals)); if ( args.length > 1 && args[1].equals("ast") ) { AstNode ast = parsetree.toAst(); if ( ast != null ) { diff --git a/wdl/README.md b/wdl/README.md new file mode 100644 index 0000000..24c6a6d --- /dev/null +++ b/wdl/README.md @@ -0,0 +1,13 @@ +Usage +===== + +There are two example .wdl files in this directory that parse: + +* MutSig.wdl +* CopyNumberQC.wdl + +To get an AbstractSyntaxTree (Ast) from a source file: + +``` + +``` diff --git a/wdl/SourceCode.java b/wdl/SourceCode.java new file mode 100644 index 0000000..45d4c26 --- /dev/null +++ b/wdl/SourceCode.java @@ -0,0 +1,10 @@ +import java.util.List; +interface SourceCode { + public void advance(int amount); + public List getLines(); + public String getLine(int lineno); + public String getString(); + public int getLine(); + public int getColumn(); + public String getResource(); +} diff --git a/wdl/SyntaxErrorFormatter.java b/wdl/SyntaxErrorFormatter.java new file mode 100644 index 0000000..292bb2d --- /dev/null +++ b/wdl/SyntaxErrorFormatter.java @@ -0,0 +1,13 @@ +import java.util.List; +interface SyntaxErrorFormatter { + /* Called when the parser runs out of tokens but isn't finished parsing. */ + String unexpected_eof(String method, List expected); + /* Called when the parser finished parsing but there are still tokens left in the stream. */ + String excess_tokens(String method, Terminal terminal); + /* Called when the parser is expecting one token and gets another. */ + String unexpected_symbol(String method, Terminal actual, List expected); + /* Called when the parser is expecing a tokens but there are no more tokens. */ + String no_more_tokens(String method, int expecting); + /* Invalid terminal is found in the token stream. */ + String invalid_terminal(String method, Terminal invalid); +} diff --git a/wdl/TokenStream.java b/wdl/TokenStream.java index 60dd51e..43710bf 100644 --- a/wdl/TokenStream.java +++ b/wdl/TokenStream.java @@ -22,22 +22,22 @@ public Terminal current() { return null; } } - public Terminal expect(int expecting) throws SyntaxError { + public Terminal expect(int expecting, SyntaxErrorFormatter syntaxErrorFormatter) throws SyntaxError { Terminal current = current(); if (current == null) { - throw new SyntaxError( "No more tokens. Expecting " + this.terminals.get(expecting) ); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(syntaxErrorFormatter.no_more_tokens(stack[2].getMethodName(), expecting)); } if (current.getId() != expecting) { - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current : ""); - throw new SyntaxError(formatter.toString()); + ArrayList expectedList = new ArrayList(); + expectedList.add(expecting); + throw new SyntaxError(syntaxErrorFormatter.unexpected_symbol(stack[2].getMethodName(), current, expectedList)); } Terminal next = advance(); if ( next != null && !this.terminals.isValid(next.getId()) ) { - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - formatter.format("Invalid symbol ID: %d (%s)", next.getId(), next.getTerminalStr()); - throw new SyntaxError(formatter.toString()); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(syntaxErrorFormatter.invalid_terminal(stack[2].getMethodName(), next)); } return current; } diff --git a/wdl/WdlParser.java b/wdl/WdlParser.java index c00815a..686fe68 100644 --- a/wdl/WdlParser.java +++ b/wdl/WdlParser.java @@ -5,62 +5,65 @@ class WdlParser implements Parser { private TokenStream tokens; private HashMap expressionParsers; + private SyntaxErrorFormatter syntaxErrorFormatter; + private Map> first; + private Map> follow; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 41, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, - { -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1 }, - { -1, -1, -1, 25, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2 }, - { -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 33, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, 29, -1, -1, -1 }, + { -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 45, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 6, -1, -1, 0, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, 23, -1 }, + { -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 2, -1, -1, -1, -1 }, + { -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1 }, + { -1, -1, 38, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 11, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, 11, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, 21, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1 }, }; public enum TerminalId { - TERMINAL_LPAREN(0, "lparen"), - TERMINAL_IN(1, "in"), - TERMINAL_INPUT(2, "input"), - TERMINAL_NUMBER(3, "number"), - TERMINAL_COLON(4, "colon"), - TERMINAL_RBRACE(5, "rbrace"), - TERMINAL_COMMA(6, "comma"), - TERMINAL_IDENTIFIER(7, "identifier"), - TERMINAL_AS(8, "as"), - TERMINAL_ASSIGN(9, "assign"), - TERMINAL_DOT(10, "dot"), - TERMINAL_LSQUARE(11, "lsquare"), - TERMINAL_COMPOSITE_TASK(12, "composite_task"), - TERMINAL_FILE(13, "file"), - TERMINAL_FOR(14, "for"), - TERMINAL_LBRACE(15, "lbrace"), - TERMINAL_STEP(16, "step"), + TERMINAL_FILE(0, "file"), + TERMINAL_LBRACE(1, "lbrace"), + TERMINAL_STEP(2, "step"), + TERMINAL_IDENTIFIER(3, "identifier"), + TERMINAL_FOR(4, "for"), + TERMINAL_STRING(5, "string"), + TERMINAL_LPAREN(6, "lparen"), + TERMINAL_COMPOSITE_TASK(7, "composite_task"), + TERMINAL_IN(8, "in"), + TERMINAL_SEMI(9, "semi"), + TERMINAL_LSQUARE(10, "lsquare"), + TERMINAL_RSQUARE(11, "rsquare"), + TERMINAL_COLON(12, "colon"), + TERMINAL_INPUT(13, "input"), + TERMINAL_RBRACE(14, "rbrace"), + TERMINAL_COMMA(15, "comma"), + TERMINAL_AS(16, "as"), TERMINAL_OUTPUT(17, "output"), - TERMINAL_SEMI(18, "semi"), - TERMINAL_RPAREN(19, "rparen"), - TERMINAL_STRING(20, "string"), - TERMINAL_RSQUARE(21, "rsquare"); + TERMINAL_NUMBER(18, "number"), + TERMINAL_ASSIGN(19, "assign"), + TERMINAL_DOT(20, "dot"), + TERMINAL_RPAREN(21, "rparen"); private final int id; private final String string; TerminalId(int id, String string) { @@ -90,15 +93,223 @@ } WdlParser() { this.expressionParsers = new HashMap(); + this.first = new HashMap>(); + this.follow = new HashMap>(); + ArrayList list; + list = new ArrayList(); + list.add(TerminalId.TERMINAL_STRING); + list.add(TerminalId.TERMINAL_IDENTIFIER); + list.add(TerminalId.TERMINAL_NUMBER); + this.first.put("task_attr_value", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + this.first.put("_gen8", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_INPUT); + this.first.put("step_input_list", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FOR); + this.first.put("for_loop", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_OUTPUT); + this.first.put("step_output_list", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("_gen6", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FILE); + this.first.put("_gen9", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FOR); + list.add(TerminalId.TERMINAL_STEP); + this.first.put("composite_task_entity", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("task_identifier", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_OUTPUT); + list.add(TerminalId.TERMINAL_INPUT); + this.first.put("_gen4", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_DOT); + this.first.put("_gen11", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("step_input", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_LSQUARE); + this.first.put("task_attrs", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("task_attr", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_LSQUARE); + this.first.put("_gen5", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + this.first.put("_gen10", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_INPUT); + list.add(TerminalId.TERMINAL_OUTPUT); + this.first.put("step_attr", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_STEP); + this.first.put("_gen2", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_STEP); + this.first.put("step", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.first.put("wdl_entity", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_AS); + this.first.put("_gen3", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FOR); + list.add(TerminalId.TERMINAL_STEP); + this.first.put("_gen1", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.first.put("composite_task", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("_gen7", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FILE); + this.first.put("step_output", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + this.first.put("variable", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_AS); + this.first.put("step_name", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.first.put("_gen0", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.first.put("wdl", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_DOT); + this.first.put("variable_member", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + list.add(TerminalId.TERMINAL_RSQUARE); + this.follow.put("task_attr_value", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("_gen8", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_OUTPUT); + list.add(TerminalId.TERMINAL_INPUT); + this.follow.put("step_input_list", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FOR); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_STEP); + this.follow.put("for_loop", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_OUTPUT); + list.add(TerminalId.TERMINAL_INPUT); + this.follow.put("step_output_list", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RSQUARE); + this.follow.put("_gen6", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("_gen9", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_FOR); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_STEP); + this.follow.put("composite_task_entity", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_AS); + this.follow.put("task_identifier", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + this.follow.put("_gen4", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("_gen11", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("step_input", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_AS); + this.follow.put("task_attrs", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_IDENTIFIER); + list.add(TerminalId.TERMINAL_RSQUARE); + this.follow.put("task_attr", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_AS); + this.follow.put("_gen5", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("_gen10", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_OUTPUT); + list.add(TerminalId.TERMINAL_INPUT); + this.follow.put("step_attr", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + this.follow.put("_gen2", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_STEP); + list.add(TerminalId.TERMINAL_RBRACE); + list.add(TerminalId.TERMINAL_FOR); + this.follow.put("step", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.follow.put("wdl_entity", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_LBRACE); + this.follow.put("_gen3", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_RBRACE); + this.follow.put("_gen1", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMPOSITE_TASK); + this.follow.put("composite_task", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("_gen7", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("step_output", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("variable", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_LBRACE); + this.follow.put("step_name", list); + list = new ArrayList(); + this.follow.put("_gen0", list); + list = new ArrayList(); + this.follow.put("wdl", list); + list = new ArrayList(); + list.add(TerminalId.TERMINAL_COMMA); + list.add(TerminalId.TERMINAL_SEMI); + this.follow.put("variable_member", list); } public TerminalMap getTerminalMap() { return new WdlTerminalMap(TerminalId.values()); } - public ParseTree parse(TokenStream tokens) throws SyntaxError { + public ParseTree parse(TokenStream tokens, SyntaxErrorFormatter syntaxErrorFormatter) throws SyntaxError { this.tokens = tokens; + this.syntaxErrorFormatter = syntaxErrorFormatter; ParseTree tree = this.parse_wdl(); if (this.tokens.current() != null) { - throw new SyntaxError("Finished parsing without consuming all tokens."); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.excess_tokens(stack[1].getMethodName(), this.tokens.current())); } return tree; } @@ -114,76 +325,91 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (22 <= terminal && terminal <= 51); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "_gen3")); + ParseTree tree = new ParseTree( new NonTerminal(22, "task_attr_value")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 15) { - return tree; - } - } if (current == null) { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + } + if (rule == 19) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - if (rule == 42) { + else if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - return tree; + else if (rule == 41) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr_value", current, new ArrayList())); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen5")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen8")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 8) { + if (current.getId() == 9) { return tree; } } if (current == null) { return tree; } - if (rule == 39) { + if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen0")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == -1) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(24, "step_input_list")); + tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 4) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); - tree.add( subtree); - subtree = this.parse__gen0(); + if (rule == 30) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse__gen7(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input_list", current, new ArrayList())); } private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); @@ -193,516 +419,448 @@ private ParseTree parse_for_loop() throws SyntaxError { ParseTree tree = new ParseTree( new NonTerminal(25, "for_loop")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 41) { + if (rule == 21) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 7); parameters.put("item", 2); parameters.put("collection", 4); tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR.id()); + next = this.tokens.expect(TerminalId.TERMINAL_FOR.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IN.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); tree.add(next); subtree = this.parse__gen2(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("for_loop", current, new ArrayList())); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "_gen2")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 5) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(26, "step_output_list")); + tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 7) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); - subtree = this.parse__gen2(); + if (rule == 15) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse__gen9(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output_list", current, new ArrayList())); } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "step")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(27, "_gen6")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 11) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 14) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 4); - parameters.put("task", 1); - parameters.put("name", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP.id()); - tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen3(); + if (rule == 29) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attr(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen4(); + subtree = this.parse__gen6(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "task_attr")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen9")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 9) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - subtree = this.parse_task_attr_value(); + if (rule == 4) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_wdl_entity() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "wdl_entity")); + ParseTree tree = new ParseTree( new NonTerminal(29, "composite_task_entity")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 36) { + if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + subtree = this.parse_for_loop(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + else if (rule == 45) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); + tree.add( subtree); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task_entity", current, new ArrayList())); } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "task_attrs")); + ParseTree tree = new ParseTree( new NonTerminal(30, "task_identifier")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } if (rule == 22) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("attributes", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen6(); + subtree = this.parse__gen5(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_identifier", current, new ArrayList())); } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "composite_task")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 14) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 19) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen1(); + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_attr(); + tree.add( subtree); + subtree = this.parse__gen4(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse__gen11() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "step_output_list")); + ParseTree tree = new ParseTree( new NonTerminal(32, "_gen11")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 15 || current.getId() == 9) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } - if (rule == 15) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - subtree = this.parse__gen9(); + if (rule == 23) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_variable_member(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "step_attr")); + ParseTree tree = new ParseTree( new NonTerminal(33, "step_input")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 23) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); - tree.add( subtree); - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - else if (rule == 44) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input", current, new ArrayList())); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "_gen8")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 18) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(34, "task_attrs")); + tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 37) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id(), this.syntaxErrorFormatter); tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen6(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attrs", current, new ArrayList())); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "variable")); + ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 31) { + if (rule == 16) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen11(); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr", current, new ArrayList())); } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "_gen11")); + ParseTree tree = new ParseTree( new NonTerminal(36, "_gen5")); tree.setList(null); if ( current != null ) { - if (current.getId() == 18 || current.getId() == 6) { + if (current.getId() == 16) { return tree; } } if (current == null) { return tree; } - if (rule == 0) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "task_attr_value")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; + ParseTree tree = new ParseTree( new NonTerminal(37, "_gen10")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } } - else if (rule == 16) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); - tree.add(next); + if (current == null) { return tree; } - else if (rule == 25) { + if (rule == 34) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen10(); + tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 18) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(38, "step_attr")); + tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 35) { + if (rule == 1) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); + subtree = this.parse_step_input_list(); tree.add( subtree); - subtree = this.parse__gen8(); + return tree; + } + else if (rule == 2) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); tree.add( subtree); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_attr", current, new ArrayList())); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen6")); + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen2")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 21) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 30) { + if (rule == 18) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); + subtree = this.parse_step(); tree.add( subtree); - subtree = this.parse__gen6(); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "step_input_list")); + ParseTree tree = new ParseTree( new NonTerminal(40, "step")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 20) { + if (rule == 44) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id()); + parameters.put("body", 4); + parameters.put("task", 1); + parameters.put("name", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen7(); + subtree = this.parse__gen4(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step", current, new ArrayList())); } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "variable_member")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 45) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_step_output() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "step_output")); + ParseTree tree = new ParseTree( new NonTerminal(41, "wdl_entity")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } if (rule == 32) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id()); - tree.add(next); - subtree = this.parse_variable(); + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl_entity", current, new ArrayList())); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen4")); - tree.setList("nlist"); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "_gen3")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == 1) { return tree; } } @@ -711,215 +869,231 @@ private ParseTree parse__gen4() throws SyntaxError { } if (rule == 33) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); - tree.add( subtree); - subtree = this.parse__gen4(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "_gen9")); - tree.setList("slist"); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen1")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 18) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 26) { + if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "step_input")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "composite_task")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 3) { + if (rule == 14) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse_variable(); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task", current, new ArrayList())); } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "composite_task_entity")); - tree.setList(null); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "_gen7")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } + } if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + return tree; } if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_step_input(); tree.add( subtree); - return tree; - } - else if (rule == 38) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + return tree; } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "wdl")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "step_output")); tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 27) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); + if (rule == 25) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output", current, new ArrayList())); } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "task_identifier")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "variable")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 17) { + if (rule == 8) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); + parameters.put("member", 1); parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen5(); + subtree = this.parse__gen11(); tree.add( subtree); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable", current, new ArrayList())); } private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "step_name")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "step_name")); tree.setList(null); if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 24) { + if (rule == 43) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id()); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_name", current, new ArrayList())); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen1")); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "_gen0")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 5) { + if (current.getId() == -1) { return tree; } } if (current == null) { return tree; } - if (rule == 21) { + if (rule == 3) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); + subtree = this.parse_wdl_entity(); tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(51, "_gen10")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 18) { - return tree; - } - } + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "wdl")); + tree.setList(null); if (current == null) { return tree; } - if (rule == 8) { + if (rule == 12) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl", current, new ArrayList())); + } + private ParseTree parse_variable_member() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[29][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(51, "variable_member")); + tree.setList(null); + if (current == null) { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + } + if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable_member", current, new ArrayList())); } } From da9f8e4a1713a107a70ef4dcf982194bd40cec48 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sat, 11 Aug 2012 21:37:32 -0400 Subject: [PATCH 028/140] Consolidating --- wdl/Lexer.java | 180 +++---- wdl/Parser.java | 2 +- wdl/ParserMain.java | 72 --- wdl/WdlMain.java | 40 ++ wdl/WdlParser.java | 995 +++++++++++++++++---------------------- wdl/WdlSourceCode.java | 88 ++++ wdl/WdlSyntaxErrorFormatter.java | 28 ++ wdl/error.wdl | 27 ++ 8 files changed, 663 insertions(+), 769 deletions(-) delete mode 100644 wdl/ParserMain.java create mode 100644 wdl/WdlMain.java create mode 100644 wdl/WdlSourceCode.java create mode 100644 wdl/WdlSyntaxErrorFormatter.java create mode 100644 wdl/error.wdl diff --git a/wdl/Lexer.java b/wdl/Lexer.java index 5d932fa..ded3436 100644 --- a/wdl/Lexer.java +++ b/wdl/Lexer.java @@ -10,82 +10,6 @@ import java.nio.charset.*; import java.nio.channels.*; -class WdlSourceCode implements SourceCode{ - private File source; - private String resource; - private String contents; - private int line; - private int col; - private StringBuilder currentLine; - private List lines; - - WdlSourceCode(String source, String resource) { - init(source, resource); - } - - WdlSourceCode(File source) throws IOException { - this(source, "utf-8", source.getCanonicalPath()); - } - - WdlSourceCode(File source, String resource) throws IOException { - this(source, "utf-8", resource); - } - - WdlSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { - FileChannel channel = new FileInputStream(source).getChannel(); - MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); - Charset cs = Charset.forName(encoding); - CharsetDecoder cd = cs.newDecoder(); - CharBuffer cb = cd.decode(buffer); - init(cb.toString(), resource); - } - - private void init(String contents, String resource) { - this.contents = contents; - this.resource = resource; - this.line = 1; - this.col = 1; - this.lines = new ArrayList(); - this.currentLine = new StringBuilder(); - } - - public void advance(int amount) { - String str = this.contents.substring(0, amount); - for ( byte b : str.getBytes() ) { - if ( b == (byte) '\n' || b == (byte) '\r' ) { - this.line++; - this.col = 1; - } else { - this.col++; - } - } - this.contents = this.contents.substring(amount); - } - - public String getString() { - return this.contents; - } - - public String getResource() { - return this.resource; - } - - public int getLine() { - return this.line; - } - - public int getColumn() { - return this.col; - } - - public String getLine(int lineno) { - return null; // TODO - } - - public List getLines() { - return null; // TODO - } -} class LexerMatch { private Terminal terminal; @@ -121,66 +45,68 @@ LexerMatch match(SourceCode source) { } public class Lexer { - public static void main(String[] args) { - // 'as', 'assign', 'colon', 'comma', 'composite_task', 'file', 'for', 'identifier', 'in', 'input', 'lbrace', 'lparen', 'lsquare', 'number', 'output', 'rbrace', 'rparen', 'rsquare', 'semi', 'step', 'string' - ArrayList regex = new ArrayList(); - regex.add( new TokenLexer(Pattern.compile("\\/\\*.*?\\*\\/", Pattern.DOTALL), null) ); - regex.add( new TokenLexer(Pattern.compile("//.*"), null) ); - regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); - regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_OUTPUT) ); - regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_INPUT) ); - regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STEP) ); - regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); - regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FOR) ); - regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_AS) ); - regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_IN) ); - regex.add( new TokenLexer(Pattern.compile("^\\."), WdlParser.TerminalId.TERMINAL_DOT) ); - regex.add( new TokenLexer(Pattern.compile("^,"), WdlParser.TerminalId.TERMINAL_COMMA) ); - regex.add( new TokenLexer(Pattern.compile("^:"), WdlParser.TerminalId.TERMINAL_COLON) ); - regex.add( new TokenLexer(Pattern.compile("^;"), WdlParser.TerminalId.TERMINAL_SEMI) ); - regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_ASSIGN) ); - regex.add( new TokenLexer(Pattern.compile("^\\["), WdlParser.TerminalId.TERMINAL_LSQUARE) ); - regex.add( new TokenLexer(Pattern.compile("^\\]"), WdlParser.TerminalId.TERMINAL_RSQUARE) ); - regex.add( new TokenLexer(Pattern.compile("^\\{"), WdlParser.TerminalId.TERMINAL_LBRACE) ); - regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); - regex.add( new TokenLexer(Pattern.compile("^\\("), WdlParser.TerminalId.TERMINAL_LPAREN) ); - regex.add( new TokenLexer(Pattern.compile("^\\)"), WdlParser.TerminalId.TERMINAL_RPAREN) ); - regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING) ); - regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), WdlParser.TerminalId.TERMINAL_IDENTIFIER) ); - regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), WdlParser.TerminalId.TERMINAL_NUMBER) ); - regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); - if ( args.length < 1 ) { - System.err.println("Usage: Lexer "); - System.exit(-1); - } - - try { - SourceCode code = new WdlSourceCode(new File(args[0])); - ArrayList terminal_strings = new ArrayList(); - boolean progress = true; + private ArrayList regex; + + Lexer() { + this.regex = new ArrayList(); + this.regex.add( new TokenLexer(Pattern.compile("\\/\\*.*?\\*\\/", Pattern.DOTALL), null) ); + this.regex.add( new TokenLexer(Pattern.compile("//.*"), null) ); + this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); + this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_OUTPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_INPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STEP) ); + this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); + this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FOR) ); + this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_AS) ); + this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_IN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\."), WdlParser.TerminalId.TERMINAL_DOT) ); + this.regex.add( new TokenLexer(Pattern.compile("^,"), WdlParser.TerminalId.TERMINAL_COMMA) ); + this.regex.add( new TokenLexer(Pattern.compile("^:"), WdlParser.TerminalId.TERMINAL_COLON) ); + this.regex.add( new TokenLexer(Pattern.compile("^;"), WdlParser.TerminalId.TERMINAL_SEMI) ); + this.regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_ASSIGN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\["), WdlParser.TerminalId.TERMINAL_LSQUARE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\]"), WdlParser.TerminalId.TERMINAL_RSQUARE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\{"), WdlParser.TerminalId.TERMINAL_LBRACE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\("), WdlParser.TerminalId.TERMINAL_LPAREN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\)"), WdlParser.TerminalId.TERMINAL_RPAREN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING) ); + this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), WdlParser.TerminalId.TERMINAL_IDENTIFIER) ); + this.regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), WdlParser.TerminalId.TERMINAL_NUMBER) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); + } - while (progress) { - progress = false; - for ( TokenLexer lexer : regex ) { - LexerMatch match = lexer.match(code); - if (match != null) { - progress = true; - if (match.getTerminal() != null) { - terminal_strings.add( " " + match.getTerminal() ); - } - break; + public List getTokens(SourceCode code) { + ArrayList tokens = new ArrayList(); + boolean progress = true; + + while (progress) { + progress = false; + for ( TokenLexer lexer : regex ) { + LexerMatch match = lexer.match(code); + if (match != null) { + progress = true; + if (match.getTerminal() != null) { + tokens.add(match.getTerminal()); } + break; } } + } + return tokens; + } + public static void main(String[] args) { + try { + SourceCode code = new WdlSourceCode(new File(args[0])); + Lexer lexer = new Lexer(); + List terminals = lexer.getTokens(code); System.out.println("["); - System.out.println( Utility.join(terminal_strings, ",\n") ); + System.out.println(Utility.join(terminals, ",\n")); System.out.println("]"); - System.out.flush(); - } catch (IOException e) { + } catch( IOException e ) { System.err.println(e); - System.exit(-1); } } } diff --git a/wdl/Parser.java b/wdl/Parser.java index 7b41d6f..8746412 100644 --- a/wdl/Parser.java +++ b/wdl/Parser.java @@ -1,4 +1,4 @@ interface Parser { - ParseTree parse(TokenStream tokens, SyntaxErrorFormatter formatter) throws SyntaxError; + ParseTree parse(TokenStream tokens) throws SyntaxError; TerminalMap getTerminalMap(); } diff --git a/wdl/ParserMain.java b/wdl/ParserMain.java deleted file mode 100644 index 1350d2b..0000000 --- a/wdl/ParserMain.java +++ /dev/null @@ -1,72 +0,0 @@ -import org.json.*; -import java.io.*; -import java.util.List; -class ParserMain { - private static class DefaultSyntaxErrorFormatter implements SyntaxErrorFormatter { - private TerminalMap map; - DefaultSyntaxErrorFormatter(TerminalMap map) { - this.map = map; - } - public String unexpected_eof(String method, List expected) { - return "Error: unexpected end of file"; - } - public String excess_tokens(String method, Terminal terminal) { - return "Finished parsing without consuming all tokens"; - } - public String unexpected_symbol(String method, Terminal actual, List expected) { - return "Unexpected symbol (" + actual.getTerminalStr() + ") when parsing " + method; - } - public String no_more_tokens(String method, int expecting) { - return "No more tokens. Expecting " + this.map.get(expecting); - } - public String invalid_terminal(String method, Terminal invalid) { - return "Invalid symbol ID: "+invalid.getId()+" ("+invalid.getTerminalStr()+")"; - } - } - private static Parser getParser(String name) throws Exception { - if (name.equals("wdl")) { - return new WdlParser(); - } - throw new Exception("Invalid grammar name: " + name); - } - public static void main(String args[]) { - final String grammars = "wdl"; - if ( args.length < 2 ) { - System.out.println("Usage: ParserMain <" + grammars + "> "); - System.exit(-1); - } - final String grammar = args[0].toLowerCase(); - try { - Parser parser = getParser(grammar); - TerminalMap terminals = parser.getTerminalMap(); - TokenStream tokens = new TokenStream(terminals); - String contents = Utility.readStdin(); - JSONArray arr = new JSONArray(contents); - for ( int i = 0; i < arr.length(); i++ ) { - JSONObject token = arr.getJSONObject(i); - tokens.add(new Terminal( - terminals.get(token.getString("terminal")), - token.getString("terminal"), - token.getString("source_string"), - token.getString("resource"), - token.getInt("line"), - token.getInt("col") - )); - } - ParseTreeNode parsetree = parser.parse(tokens, new DefaultSyntaxErrorFormatter(terminals)); - if ( args.length > 1 && args[1].equals("ast") ) { - AstNode ast = parsetree.toAst(); - if ( ast != null ) { - System.out.println(ast.toPrettyString()); - } else { - System.out.println("None"); - } - } else { - System.out.println(parsetree.toPrettyString()); - } - } catch (Exception e) { - System.err.println(e.getMessage()); - System.exit(-1); - } - } -} diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java new file mode 100644 index 0000000..b5bac0b --- /dev/null +++ b/wdl/WdlMain.java @@ -0,0 +1,40 @@ +import java.io.File; +import java.io.IOException; + +class WdlMain { + public static void main(String[] args) { + WdlSyntaxErrorFormatter error_formatter = new WdlSyntaxErrorFormatter(); + SourceCode code = null; + + try { + code = new WdlSourceCode(new File(args[0])); + } catch (IOException error) { + System.err.println(error); + System.exit(-1); + } + + Lexer lexer = new Lexer(); + WdlParser parser = new WdlParser(error_formatter); + TerminalMap terminals = parser.getTerminalMap(); + TokenStream tokens = new TokenStream(terminals); + tokens.addAll(lexer.getTokens(code)); + error_formatter.setTerminalMap(terminals); + + try { + ParseTreeNode parsetree = parser.parse(tokens); + + if ( args.length >= 2 && args[1].equals("ast") ) { + AstNode ast = parsetree.toAst(); + if ( ast != null ) { + System.out.println(ast.toPrettyString()); + } else { + System.out.println("None"); + } + } else { + System.out.println(parsetree.toPrettyString()); + } + } catch (SyntaxError error) { + System.err.println(error); + } + } +} diff --git a/wdl/WdlParser.java b/wdl/WdlParser.java index 686fe68..9a53f71 100644 --- a/wdl/WdlParser.java +++ b/wdl/WdlParser.java @@ -6,64 +6,64 @@ private TokenStream tokens; private HashMap expressionParsers; private SyntaxErrorFormatter syntaxErrorFormatter; - private Map> first; - private Map> follow; + private Map first; + private Map follow; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, 41, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1 }, - { -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 45, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 6, -1, -1, 0, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, 23, -1 }, - { -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 2, -1, -1, -1, -1 }, - { -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1 }, - { -1, -1, 38, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 11, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1 }, + { 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 28, -1, -1, -1, -1 }, + { 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 19, -1, 19, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 2, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, 26, -1, -1 }, + { 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1 }, + { -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 23, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 4 }, + { -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, 0, -1, 0, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, 25, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 8, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId { - TERMINAL_FILE(0, "file"), - TERMINAL_LBRACE(1, "lbrace"), - TERMINAL_STEP(2, "step"), - TERMINAL_IDENTIFIER(3, "identifier"), - TERMINAL_FOR(4, "for"), - TERMINAL_STRING(5, "string"), - TERMINAL_LPAREN(6, "lparen"), - TERMINAL_COMPOSITE_TASK(7, "composite_task"), - TERMINAL_IN(8, "in"), - TERMINAL_SEMI(9, "semi"), - TERMINAL_LSQUARE(10, "lsquare"), - TERMINAL_RSQUARE(11, "rsquare"), - TERMINAL_COLON(12, "colon"), - TERMINAL_INPUT(13, "input"), + TERMINAL_STEP(0, "step"), + TERMINAL_STRING(1, "string"), + TERMINAL_LPAREN(2, "lparen"), + TERMINAL_LSQUARE(3, "lsquare"), + TERMINAL_IN(4, "in"), + TERMINAL_RPAREN(5, "rparen"), + TERMINAL_LBRACE(6, "lbrace"), + TERMINAL_INPUT(7, "input"), + TERMINAL_NUMBER(8, "number"), + TERMINAL_OUTPUT(9, "output"), + TERMINAL_FILE(10, "file"), + TERMINAL_AS(11, "as"), + TERMINAL_DOT(12, "dot"), + TERMINAL_SEMI(13, "semi"), TERMINAL_RBRACE(14, "rbrace"), TERMINAL_COMMA(15, "comma"), - TERMINAL_AS(16, "as"), - TERMINAL_OUTPUT(17, "output"), - TERMINAL_NUMBER(18, "number"), - TERMINAL_ASSIGN(19, "assign"), - TERMINAL_DOT(20, "dot"), - TERMINAL_RPAREN(21, "rparen"); + TERMINAL_COMPOSITE_TASK(16, "composite_task"), + TERMINAL_FOR(17, "for"), + TERMINAL_ASSIGN(18, "assign"), + TERMINAL_IDENTIFIER(19, "identifier"), + TERMINAL_COLON(20, "colon"), + TERMINAL_RSQUARE(21, "rsquare"); private final int id; private final String string; TerminalId(int id, String string) { @@ -91,221 +91,78 @@ public boolean isValid(String string) { return this.str_to_id.containsKey(string); } public boolean isValid(int id) { return this.id_to_str.containsKey(id); } } - WdlParser() { + WdlParser(SyntaxErrorFormatter syntaxErrorFormatter) { + this.syntaxErrorFormatter = syntaxErrorFormatter; this.expressionParsers = new HashMap(); - this.first = new HashMap>(); - this.follow = new HashMap>(); + this.first = new HashMap(); + this.follow = new HashMap(); ArrayList list; - list = new ArrayList(); - list.add(TerminalId.TERMINAL_STRING); - list.add(TerminalId.TERMINAL_IDENTIFIER); - list.add(TerminalId.TERMINAL_NUMBER); - this.first.put("task_attr_value", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - this.first.put("_gen8", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_INPUT); - this.first.put("step_input_list", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FOR); - this.first.put("for_loop", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_OUTPUT); - this.first.put("step_output_list", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("_gen6", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FILE); - this.first.put("_gen9", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FOR); - list.add(TerminalId.TERMINAL_STEP); - this.first.put("composite_task_entity", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("task_identifier", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_OUTPUT); - list.add(TerminalId.TERMINAL_INPUT); - this.first.put("_gen4", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_DOT); - this.first.put("_gen11", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("step_input", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_LSQUARE); - this.first.put("task_attrs", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("task_attr", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_LSQUARE); - this.first.put("_gen5", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - this.first.put("_gen10", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_INPUT); - list.add(TerminalId.TERMINAL_OUTPUT); - this.first.put("step_attr", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_STEP); - this.first.put("_gen2", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_STEP); - this.first.put("step", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.first.put("wdl_entity", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_AS); - this.first.put("_gen3", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FOR); - list.add(TerminalId.TERMINAL_STEP); - this.first.put("_gen1", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.first.put("composite_task", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("_gen7", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FILE); - this.first.put("step_output", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - this.first.put("variable", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_AS); - this.first.put("step_name", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.first.put("_gen0", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.first.put("wdl", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_DOT); - this.first.put("variable_member", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - list.add(TerminalId.TERMINAL_RSQUARE); - this.follow.put("task_attr_value", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("_gen8", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_OUTPUT); - list.add(TerminalId.TERMINAL_INPUT); - this.follow.put("step_input_list", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FOR); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_STEP); - this.follow.put("for_loop", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_OUTPUT); - list.add(TerminalId.TERMINAL_INPUT); - this.follow.put("step_output_list", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RSQUARE); - this.follow.put("_gen6", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("_gen9", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_FOR); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_STEP); - this.follow.put("composite_task_entity", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_AS); - this.follow.put("task_identifier", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - this.follow.put("_gen4", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("_gen11", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("step_input", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_AS); - this.follow.put("task_attrs", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_IDENTIFIER); - list.add(TerminalId.TERMINAL_RSQUARE); - this.follow.put("task_attr", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_AS); - this.follow.put("_gen5", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("_gen10", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_OUTPUT); - list.add(TerminalId.TERMINAL_INPUT); - this.follow.put("step_attr", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - this.follow.put("_gen2", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_STEP); - list.add(TerminalId.TERMINAL_RBRACE); - list.add(TerminalId.TERMINAL_FOR); - this.follow.put("step", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.follow.put("wdl_entity", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_LBRACE); - this.follow.put("_gen3", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_RBRACE); - this.follow.put("_gen1", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMPOSITE_TASK); - this.follow.put("composite_task", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("_gen7", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("step_output", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("variable", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_LBRACE); - this.follow.put("step_name", list); - list = new ArrayList(); - this.follow.put("_gen0", list); - list = new ArrayList(); - this.follow.put("wdl", list); - list = new ArrayList(); - list.add(TerminalId.TERMINAL_COMMA); - list.add(TerminalId.TERMINAL_SEMI); - this.follow.put("variable_member", list); + this.first.put("step_input", new TerminalId[] { }); + this.first.put("_gen1", new TerminalId[] { }); + this.first.put("composite_task_entity", new TerminalId[] { }); + this.first.put("step_output_list", new TerminalId[] { }); + this.first.put("step_name", new TerminalId[] { }); + this.first.put("task_attr", new TerminalId[] { }); + this.first.put("_gen4", new TerminalId[] { }); + this.first.put("task_attr_value", new TerminalId[] { }); + this.first.put("_gen3", new TerminalId[] { }); + this.first.put("_gen7", new TerminalId[] { }); + this.first.put("_gen2", new TerminalId[] { }); + this.first.put("wdl", new TerminalId[] { }); + this.first.put("task_attrs", new TerminalId[] { }); + this.first.put("variable", new TerminalId[] { }); + this.first.put("step_output", new TerminalId[] { }); + this.first.put("step_attr", new TerminalId[] { }); + this.first.put("_gen9", new TerminalId[] { }); + this.first.put("_gen6", new TerminalId[] { }); + this.first.put("_gen5", new TerminalId[] { }); + this.first.put("step", new TerminalId[] { }); + this.first.put("wdl_entity", new TerminalId[] { }); + this.first.put("composite_task", new TerminalId[] { }); + this.first.put("_gen11", new TerminalId[] { }); + this.first.put("_gen0", new TerminalId[] { }); + this.first.put("step_input_list", new TerminalId[] { }); + this.first.put("_gen8", new TerminalId[] { }); + this.first.put("task_identifier", new TerminalId[] { }); + this.first.put("for_loop", new TerminalId[] { }); + this.first.put("_gen10", new TerminalId[] { }); + this.first.put("variable_member", new TerminalId[] { }); + this.follow.put("step_input", new TerminalId[] { }); + this.follow.put("_gen1", new TerminalId[] { }); + this.follow.put("composite_task_entity", new TerminalId[] { }); + this.follow.put("step_output_list", new TerminalId[] { }); + this.follow.put("step_name", new TerminalId[] { }); + this.follow.put("task_attr", new TerminalId[] { }); + this.follow.put("_gen4", new TerminalId[] { }); + this.follow.put("task_attr_value", new TerminalId[] { }); + this.follow.put("_gen3", new TerminalId[] { }); + this.follow.put("_gen7", new TerminalId[] { }); + this.follow.put("_gen2", new TerminalId[] { }); + this.follow.put("wdl", new TerminalId[] { }); + this.follow.put("task_attrs", new TerminalId[] { }); + this.follow.put("variable", new TerminalId[] { }); + this.follow.put("step_output", new TerminalId[] { }); + this.follow.put("step_attr", new TerminalId[] { }); + this.follow.put("_gen9", new TerminalId[] { }); + this.follow.put("_gen6", new TerminalId[] { }); + this.follow.put("_gen5", new TerminalId[] { }); + this.follow.put("step", new TerminalId[] { }); + this.follow.put("wdl_entity", new TerminalId[] { }); + this.follow.put("composite_task", new TerminalId[] { }); + this.follow.put("_gen11", new TerminalId[] { }); + this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("step_input_list", new TerminalId[] { }); + this.follow.put("_gen8", new TerminalId[] { }); + this.follow.put("task_identifier", new TerminalId[] { }); + this.follow.put("for_loop", new TerminalId[] { }); + this.follow.put("_gen10", new TerminalId[] { }); + this.follow.put("variable_member", new TerminalId[] { }); } public TerminalMap getTerminalMap() { return new WdlTerminalMap(TerminalId.values()); } - public ParseTree parse(TokenStream tokens, SyntaxErrorFormatter syntaxErrorFormatter) throws SyntaxError { + public ParseTree parse(TokenStream tokens) throws SyntaxError { this.tokens = tokens; - this.syntaxErrorFormatter = syntaxErrorFormatter; ParseTree tree = this.parse_wdl(); if (this.tokens.current() != null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); @@ -325,330 +182,302 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (22 <= terminal && terminal <= 51); } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "task_attr_value")); + ParseTree tree = new ParseTree( new NonTerminal(22, "step_input")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 19) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); - tree.add(next); - return tree; - } - else if (rule == 24) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id(), this.syntaxErrorFormatter); - tree.add(next); - return tree; - } - else if (rule == 41) { - tree.setAstTransformation(new AstTransformSubstitution(0)); + if (rule == 29) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr_value", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input", current, new ArrayList())); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen8")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen1")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 9) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 27) { + if (rule == 28) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "step_input_list")); + ParseTree tree = new ParseTree( new NonTerminal(24, "composite_task_entity")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 30) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse__gen7(); + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); - tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input_list", current, new ArrayList())); + else if (rule == 34) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_for_loop(); + tree.add( subtree); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task_entity", current, new ArrayList())); } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "for_loop")); + ParseTree tree = new ParseTree( new NonTerminal(25, "step_output_list")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 21) { + if (rule == 27) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse__gen9(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("for_loop", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output_list", current, new ArrayList())); } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "step_output_list")); + ParseTree tree = new ParseTree( new NonTerminal(26, "step_name")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 15) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); + if (rule == 18) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen9(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output_list", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_name", current, new ArrayList())); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "_gen6")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 11) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(27, "task_attr")); + tree.setList(null); if (current == null) { - return tree; + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 29) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); - tree.add( subtree); - subtree = this.parse__gen6(); + if (rule == 44) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr", current, new ArrayList())); } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen9")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen4")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 9) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 4) { + if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "composite_task_entity")); + ParseTree tree = new ParseTree( new NonTerminal(29, "task_attr_value")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 37) { + if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - else if (rule == 45) { + else if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task_entity", current, new ArrayList())); + else if (rule == 39) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id(), this.syntaxErrorFormatter); + tree.add(next); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr_value", current, new ArrayList())); } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "task_identifier")); + ParseTree tree = new ParseTree( new NonTerminal(30, "_gen3")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 6) { + return tree; + } + } if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } - if (rule == 22) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse__gen5(); + if (rule == 6) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_identifier", current, new ArrayList())); + return tree; } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); - tree.setList("nlist"); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen7")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 0) { + if (rule == 26) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen4(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "_gen11")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(32, "_gen2")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 15 || current.getId() == 9) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 23) { + if (rule == 12) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_step(); + tree.add( subtree); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "step_input")); + ParseTree tree = new ParseTree( new NonTerminal(33, "wdl")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } - if (rule == 28) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse_variable(); + if (rule == 43) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl", current, new ArrayList())); } private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); @@ -661,7 +490,7 @@ private ParseTree parse_task_attrs() throws SyntaxError { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 9) { + if (rule == 36) { tree.setAstTransformation(new AstTransformSubstitution(1)); next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id(), this.syntaxErrorFormatter); tree.add(next); @@ -673,75 +502,104 @@ private ParseTree parse_task_attrs() throws SyntaxError { } throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attrs", current, new ArrayList())); } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr")); + ParseTree tree = new ParseTree( new NonTerminal(35, "variable")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 16) { + if (rule == 13) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + subtree = this.parse__gen11(); + tree.add( subtree); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable", current, new ArrayList())); + } + private ParseTree parse_step_output() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "step_output")); + tree.setList(null); + if (current == null) { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + } + if (rule == 41) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse_task_attr_value(); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output", current, new ArrayList())); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "_gen5")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "step_attr")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 16) { - return tree; - } - } if (current == null) { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + } + if (rule == 23) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input_list(); + tree.add( subtree); return tree; } - if (rule == 42) { + else if (rule == 31) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + subtree = this.parse_step_output_list(); tree.add( subtree); return tree; } - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_attr", current, new ArrayList())); } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "_gen10")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen9")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 9) { + if (current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 34) { + if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); - tree.add(next); - tree.setListSeparator(next); subtree = this.parse_step_output(); tree.add( subtree); subtree = this.parse__gen10(); @@ -750,51 +608,49 @@ private ParseTree parse__gen10() throws SyntaxError { } return tree; } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "step_attr")); - tree.setList(null); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen6")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 21) { + return tree; + } + } if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } if (rule == 1) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); + subtree = this.parse_task_attr(); tree.add( subtree); - return tree; - } - else if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + subtree = this.parse__gen6(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_attr", current, new ArrayList())); + return tree; } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen2")); - tree.setList("nlist"); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen5")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == 11) { return tree; } } if (current == null) { return tree; } - if (rule == 18) { + if (rule == 32) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); - subtree = this.parse__gen2(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } @@ -804,14 +660,14 @@ private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "step")); + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "step")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 44) { + if (rule == 22) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 4); parameters.put("task", 1); @@ -837,14 +693,14 @@ private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "wdl_entity")); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "wdl_entity")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 32) { + if (rule == 3) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_composite_task(); tree.add( subtree); @@ -852,101 +708,131 @@ private ParseTree parse_wdl_entity() throws SyntaxError { } throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl_entity", current, new ArrayList())); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "_gen3")); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "composite_task")); + tree.setList(null); + if (current == null) { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + } + if (rule == 17) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); + return tree; + } + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task", current, new ArrayList())); + } + private ParseTree parse__gen11() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "_gen11")); tree.setList(null); if ( current != null ) { - if (current.getId() == 1) { + if (current.getId() == 15 || current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 33) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen1")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "_gen0")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == -1) { return tree; } } if (current == null) { return tree; } - if (rule == 38) { + if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); + subtree = this.parse_wdl_entity(); tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "composite_task")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "step_input_list")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 14) { + if (rule == 10) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id(), this.syntaxErrorFormatter); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse__gen7(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input_list", current, new ArrayList())); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "_gen7")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen8")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 9) { + if (current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 11) { + if (rule == 25) { tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); + tree.add(next); + tree.setListSeparator(next); subtree = this.parse_step_input(); tree.add( subtree); subtree = this.parse__gen8(); @@ -955,126 +841,97 @@ private ParseTree parse__gen7() throws SyntaxError { } return tree; } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "step_output")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "task_identifier")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 25) { + if (rule == 7) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + parameters.put("attributes", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_identifier", current, new ArrayList())); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "variable")); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "for_loop")); tree.setList(null); if (current == null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 8) { + if (rule == 14) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); - subtree = this.parse__gen11(); - tree.add( subtree); - return tree; - } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable", current, new ArrayList())); - } - private ParseTree parse_step_name() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "step_name")); - tree.setList(null); - if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); - } - if (rule == 43) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_IN.id(), this.syntaxErrorFormatter); tree.add(next); next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_name", current, new ArrayList())); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("for_loop", current, new ArrayList())); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "_gen0")); - tree.setList("nlist"); + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen10")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 3) { + if (rule == 8) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_wdl() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "wdl")); - tree.setList(null); - if (current == null) { - return tree; - } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); - tree.add( subtree); - return tree; - } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl", current, new ArrayList())); - } private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; @@ -1086,7 +943,7 @@ private ParseTree parse_variable_member() throws SyntaxError { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); } - if (rule == 31) { + if (rule == 33) { tree.setAstTransformation(new AstTransformSubstitution(1)); next = this.tokens.expect(TerminalId.TERMINAL_DOT.id(), this.syntaxErrorFormatter); tree.add(next); diff --git a/wdl/WdlSourceCode.java b/wdl/WdlSourceCode.java new file mode 100644 index 0000000..c47c76e --- /dev/null +++ b/wdl/WdlSourceCode.java @@ -0,0 +1,88 @@ +import java.io.File; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.nio.channels.FileChannel; +import java.nio.MappedByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.CharBuffer; +import java.util.ArrayList; +import java.util.List; +import java.io.FileInputStream; + +class WdlSourceCode implements SourceCode{ + private File source; + private String resource; + private String contents; + private int line; + private int col; + private StringBuilder currentLine; + private List lines; + + WdlSourceCode(String source, String resource) { + init(source, resource); + } + + WdlSourceCode(File source) throws IOException { + this(source, "utf-8", source.getCanonicalPath()); + } + + WdlSourceCode(File source, String resource) throws IOException { + this(source, "utf-8", resource); + } + + WdlSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { + FileChannel channel = new FileInputStream(source).getChannel(); + MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); + Charset cs = Charset.forName(encoding); + CharsetDecoder cd = cs.newDecoder(); + CharBuffer cb = cd.decode(buffer); + init(cb.toString(), resource); + } + + private void init(String contents, String resource) { + this.contents = contents; + this.resource = resource; + this.line = 1; + this.col = 1; + this.lines = new ArrayList(); + this.currentLine = new StringBuilder(); + } + + public void advance(int amount) { + String str = this.contents.substring(0, amount); + for ( byte b : str.getBytes() ) { + if ( b == (byte) '\n' || b == (byte) '\r' ) { + this.line++; + this.col = 1; + } else { + this.col++; + } + } + this.contents = this.contents.substring(amount); + } + + public String getString() { + return this.contents; + } + + public String getResource() { + return this.resource; + } + + public int getLine() { + return this.line; + } + + public int getColumn() { + return this.col; + } + + public String getLine(int lineno) { + return null; // TODO + } + + public List getLines() { + return null; // TODO + } +} diff --git a/wdl/WdlSyntaxErrorFormatter.java b/wdl/WdlSyntaxErrorFormatter.java new file mode 100644 index 0000000..10e462c --- /dev/null +++ b/wdl/WdlSyntaxErrorFormatter.java @@ -0,0 +1,28 @@ +import java.util.ArrayList; +import java.util.List; + +class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { + private TerminalMap map; + public void setTerminalMap(TerminalMap map) { + this.map = map; + } + public String unexpected_eof(String method, List expected) { + return "Error: unexpected end of file"; + } + public String excess_tokens(String method, Terminal terminal) { + return "Finished parsing without consuming all tokens."; + } + public String unexpected_symbol(String method, Terminal actual, List expected) { + ArrayList expected_terminals = new ArrayList(); + for ( Integer e : expected ) { + expected_terminals.add(this.map.get(e.intValue())); + } + return "Unexpected symbol when parsing " + method + ". Expected " + Utility.join(expected_terminals, ", ") + ", got " + actual.getTerminalStr() + "."; + } + public String no_more_tokens(String method, int expecting) { + return "No more tokens. Expecting " + this.map.get(expecting); + } + public String invalid_terminal(String method, Terminal invalid) { + return "Invalid symbol ID: "+invalid.getId()+" ("+invalid.getTerminalStr()+")"; + } +} diff --git a/wdl/error.wdl b/wdl/error.wdl new file mode 100644 index 0000000..5ebb85f --- /dev/null +++ b/wdl/error.wdl @@ -0,0 +1,27 @@ +/* inputs: + * 1) MutSigPreprocess.{individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile} + * 2) ProcessCoverageForMutSig has no variables. All inputs come from prior step. + * 3) MutSigRun.{individual_set_id, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, jobcount} + */ + +composite_task MutSig { + + step MutSigPreprocess[verson=86] { + output: File("coverage.prepare.txt") as coverage_prepare_file, + File("patients.txt") as patient_list,, + File("${individual_set_id}.maf") as mutation_list, + File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; + } + + step ProcessCoverageForMutSig[version=75] { + input: coverage=coverage_prepare_file, patients=patient_list, mutations=mutation_list; + output: File("coverage.mat") as coverage_file, + File("mutcategs.txt") as category_file; + } + + step MutSigRun[version=157] as MutSig { + input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file=category_file, mutation_preprocessing_report=foobar; + output: File("bargraphs.png") as graphs; + } + +} From 96a821af00dc602731116e9409142c1388f4bcf1 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sun, 12 Aug 2012 17:45:04 -0400 Subject: [PATCH 029/140] More work on compiler --- wdl/CompositeTask.java | 123 ++++ wdl/Lexer.java | 2 +- wdl/MutSig.wdl | 2 +- wdl/SyntaxErrorFormatter.java | 6 +- wdl/Terminal.java | 12 +- wdl/TerminalIdentifier.java | 4 + wdl/TokenStream.java | 33 +- wdl/WdlMain.java | 34 +- wdl/WdlParser.java | 1287 ++++++++++++++++++++++++-------------- wdl/WdlSourceCode.java | 7 +- wdl/WdlSyntaxErrorFormatter.java | 55 +- wdl/error.wdl | 27 - 12 files changed, 1027 insertions(+), 565 deletions(-) create mode 100644 wdl/CompositeTask.java create mode 100644 wdl/TerminalIdentifier.java delete mode 100644 wdl/error.wdl diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java new file mode 100644 index 0000000..479ca8e --- /dev/null +++ b/wdl/CompositeTask.java @@ -0,0 +1,123 @@ +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +class CompositeTask { + + private ParseTree parse_tree; + private Ast ast; + private WdlSyntaxErrorFormatter error_formatter; + + private class CompositeTaskAstVerifier { + private WdlSyntaxErrorFormatter syntaxErrorFormatter; + + CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { + this.syntaxErrorFormatter = syntaxErrorFormatter; + } + + public Ast verify(AstNode wdl_ast) throws SyntaxError { + if ( !(wdl_ast instanceof AstList) ) { + throw new SyntaxError("Ast is not a list"); + } + + if ( ((AstList) wdl_ast).size() != 1 ) { + throw new SyntaxError("Composite Task definition should contain only one top level composite_task definition."); + } + + Ast composite_task = (Ast) ((AstList) wdl_ast).get(0); + + /* a) Error on two 'input' or 'output' in a Step + * b) Step names are unique in their scope (global or for) + * c) No version specified for task + * d) Two outputs have the same name + */ + + AstList steps = (AstList) composite_task.getAttribute("body"); + for ( AstNode step : steps ) { + Ast step_ast = (Ast) step; + Ast task = (Ast) step_ast.getAttribute("task"); + AstList task_attrs = (AstList) task.getAttribute("attributes"); + + boolean version_found = false; + + for ( AstNode task_attr : task_attrs ) { + Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); + if ( key.getSourceString().equals("version") ) { + version_found = true; + } + } + + if ( version_found == false ) { + Terminal task_name = getTaskName(step_ast); + throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); + } + } + + return composite_task; + } + + private Terminal getTaskName(Ast step) { + return (Terminal) ((Ast)step.getAttribute("task")).getAttribute("name"); + } + } + + /** Constructors **/ + + CompositeTask(SourceCode source_code) throws SyntaxError { + this.error_formatter = new WdlSyntaxErrorFormatter(); + this.error_formatter.setSourceCode(source_code); + ParseTreeNode node = getParseTree(source_code); + this.parse_tree = (ParseTree) node; + AstList ast_list = (AstList) node.toAst(); + CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); + this.ast = verifier.verify(ast_list); + } + + CompositeTask(File source_code) throws SyntaxError, IOException { + this(new WdlSourceCode(source_code)); + } + + CompositeTask(String source_code, String resource) throws SyntaxError { + this(new WdlSourceCode(source_code, resource)); + } + + /** Public Methods **/ + + public ParseTree getParseTree() { + return this.parse_tree; + } + + public Ast getAst() { + return this.ast; + } + + public Map getSteps() { + Map map = new HashMap(); + AstList steps = (AstList) this.ast.getAttribute("body"); + for ( AstNode step : steps ) { + Ast step_ast = (Ast) step; + if ( step_ast.getName().equals("Step") ) { + map.put(getStepName(step_ast), step_ast); + } + } + return map; + } + + /** Private methods **/ + private String getStepName(Ast step) { + Terminal name = (Terminal) step.getAttribute("name"); + Terminal task_name = (Terminal) ((Ast)step.getAttribute("task")).getAttribute("name"); + return (name != null) ? name.getSourceString() : task_name.getSourceString(); + } + + private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { + WdlParser parser = new WdlParser(this.error_formatter); + Lexer lexer = new Lexer(); + List terminals = lexer.getTokens(source_code); + TokenStream tokens = new TokenStream(terminals); + return parser.parse(tokens); + } +} diff --git a/wdl/Lexer.java b/wdl/Lexer.java index ded3436..5b59b2d 100644 --- a/wdl/Lexer.java +++ b/wdl/Lexer.java @@ -34,7 +34,7 @@ LexerMatch match(SourceCode source) { String sourceString = m.group(); if (this.terminal != null) - rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getColumn())); + rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), sourceString, source.getResource(), source.getLine(), source.getColumn())); else rval = new LexerMatch(); diff --git a/wdl/MutSig.wdl b/wdl/MutSig.wdl index ea7a538..7ae645c 100644 --- a/wdl/MutSig.wdl +++ b/wdl/MutSig.wdl @@ -6,7 +6,7 @@ composite_task MutSig { - step MutSigPreprocess[verson=86] { + step MutSigPreprocess[version=86] { output: File("coverage.prepare.txt") as coverage_prepare_file, File("patients.txt") as patient_list, File("${individual_set_id}.maf") as mutation_list, diff --git a/wdl/SyntaxErrorFormatter.java b/wdl/SyntaxErrorFormatter.java index 292bb2d..caf9db6 100644 --- a/wdl/SyntaxErrorFormatter.java +++ b/wdl/SyntaxErrorFormatter.java @@ -1,13 +1,13 @@ import java.util.List; interface SyntaxErrorFormatter { /* Called when the parser runs out of tokens but isn't finished parsing. */ - String unexpected_eof(String method, List expected); + String unexpected_eof(String method, List expected, List nt_rules); /* Called when the parser finished parsing but there are still tokens left in the stream. */ String excess_tokens(String method, Terminal terminal); /* Called when the parser is expecting one token and gets another. */ - String unexpected_symbol(String method, Terminal actual, List expected); + String unexpected_symbol(String method, Terminal actual, List expected, String rule); /* Called when the parser is expecing a tokens but there are no more tokens. */ - String no_more_tokens(String method, int expecting); + String no_more_tokens(String method, TerminalIdentifier expecting, Terminal last); /* Invalid terminal is found in the token stream. */ String invalid_terminal(String method, Terminal invalid); } diff --git a/wdl/Terminal.java b/wdl/Terminal.java index ab54dab..f187065 100644 --- a/wdl/Terminal.java +++ b/wdl/Terminal.java @@ -4,14 +4,14 @@ { private int id; private String terminal_str; - private String base64_source_string; + private String source_string; private String resource; private int line; private int col; - Terminal(int id, String terminal_str, String base64_source_string, String resource, int line, int col) { + Terminal(int id, String terminal_str, String source_string, String resource, int line, int col) { this.id = id; this.terminal_str = terminal_str; - this.base64_source_string = base64_source_string; + this.source_string = source_string; this.resource = resource; this.line = line; this.col = col; @@ -22,8 +22,8 @@ public int getId() { public String getTerminalStr() { return this.terminal_str; } - public String getBase64SourceString() { - return this.base64_source_string; + public String getSourceString() { + return this.source_string; } public String getResource() { return this.resource; @@ -37,7 +37,7 @@ public int getColumn() { public String toString() { StringBuilder sb = new StringBuilder(); Formatter formatter = new Formatter(sb, Locale.US); - formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), this.getBase64SourceString()); + formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), Utility.base64_encode(this.getSourceString().getBytes())); return formatter.toString(); } public String toPrettyString() { diff --git a/wdl/TerminalIdentifier.java b/wdl/TerminalIdentifier.java new file mode 100644 index 0000000..453b513 --- /dev/null +++ b/wdl/TerminalIdentifier.java @@ -0,0 +1,4 @@ +interface TerminalIdentifier { + public int id(); + public String string(); +} diff --git a/wdl/TokenStream.java b/wdl/TokenStream.java index 43710bf..cd7cc95 100644 --- a/wdl/TokenStream.java +++ b/wdl/TokenStream.java @@ -1,13 +1,24 @@ import java.util.ArrayList; +import java.util.List; import java.util.Formatter; import java.util.Locale; class TokenStream extends ArrayList { private int index; private TerminalMap terminals; - TokenStream(TerminalMap terminals) { - this.terminals = terminals; + private SyntaxErrorFormatter syntaxErrorFormatter; + TokenStream(List terminals) { + super(terminals); + reset(); + } + TokenStream() { reset(); } + public void setTerminalMap(TerminalMap terminals) { + this.terminals = terminals; + } + public void setSyntaxErrorFormatter(SyntaxErrorFormatter syntaxErrorFormatter) { + this.syntaxErrorFormatter = syntaxErrorFormatter; + } public void reset() { this.index = 0; } @@ -22,22 +33,22 @@ public Terminal current() { return null; } } - public Terminal expect(int expecting, SyntaxErrorFormatter syntaxErrorFormatter) throws SyntaxError { + public Terminal last() { + return this.get(this.size() - 1); + } + public Terminal expect(TerminalIdentifier expecting, String nonterminal, String rule) throws SyntaxError { Terminal current = current(); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(syntaxErrorFormatter.no_more_tokens(stack[2].getMethodName(), expecting)); + throw new SyntaxError(syntaxErrorFormatter.no_more_tokens(nonterminal, expecting, last())); } - if (current.getId() != expecting) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - ArrayList expectedList = new ArrayList(); + if (current.getId() != expecting.id()) { + ArrayList expectedList = new ArrayList(); expectedList.add(expecting); - throw new SyntaxError(syntaxErrorFormatter.unexpected_symbol(stack[2].getMethodName(), current, expectedList)); + throw new SyntaxError(syntaxErrorFormatter.unexpected_symbol(nonterminal, current, expectedList, rule)); } Terminal next = advance(); if ( next != null && !this.terminals.isValid(next.getId()) ) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(syntaxErrorFormatter.invalid_terminal(stack[2].getMethodName(), next)); + throw new SyntaxError(syntaxErrorFormatter.invalid_terminal(nonterminal, next)); } return current; } diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index b5bac0b..3b73bea 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -1,40 +1,24 @@ import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.Map; class WdlMain { public static void main(String[] args) { - WdlSyntaxErrorFormatter error_formatter = new WdlSyntaxErrorFormatter(); - SourceCode code = null; try { - code = new WdlSourceCode(new File(args[0])); + CompositeTask wdl = new CompositeTask(new File(args[0])); + Ast ast = wdl.getAst(); + Map steps = wdl.getSteps(); + for ( Map.Entry entry : steps.entrySet() ) { + System.out.println("--- Step " + entry.getKey()); + } } catch (IOException error) { System.err.println(error); System.exit(-1); - } - - Lexer lexer = new Lexer(); - WdlParser parser = new WdlParser(error_formatter); - TerminalMap terminals = parser.getTerminalMap(); - TokenStream tokens = new TokenStream(terminals); - tokens.addAll(lexer.getTokens(code)); - error_formatter.setTerminalMap(terminals); - - try { - ParseTreeNode parsetree = parser.parse(tokens); - - if ( args.length >= 2 && args[1].equals("ast") ) { - AstNode ast = parsetree.toAst(); - if ( ast != null ) { - System.out.println(ast.toPrettyString()); - } else { - System.out.println("None"); - } - } else { - System.out.println(parsetree.toPrettyString()); - } } catch (SyntaxError error) { System.err.println(error); + System.exit(-1); } } } diff --git a/wdl/WdlParser.java b/wdl/WdlParser.java index 9a53f71..80b5f46 100644 --- a/wdl/WdlParser.java +++ b/wdl/WdlParser.java @@ -2,68 +2,71 @@ import java.util.*; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Arrays; class WdlParser implements Parser { private TokenStream tokens; private HashMap expressionParsers; private SyntaxErrorFormatter syntaxErrorFormatter; - private Map first; - private Map follow; + private Map first; + private Map follow; + private Map> nonterminal_rules; + private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1 }, - { 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 28, -1, -1, -1, -1 }, - { 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1 }, + { -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1 }, + { 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 31, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 15, 15, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, 39, -1, -1, -1 }, + { -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 21, -1, -1, 21, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 19, -1, 19, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 2, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, 26, -1, -1 }, - { 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 23, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 4 }, - { -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10 }, + { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1 }, + { 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32 }, + { -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, 0, -1, 0, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, 25, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 8, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, 30, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, + { -1, -1, 26, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1 }, }; - public enum TerminalId { - TERMINAL_STEP(0, "step"), - TERMINAL_STRING(1, "string"), - TERMINAL_LPAREN(2, "lparen"), - TERMINAL_LSQUARE(3, "lsquare"), - TERMINAL_IN(4, "in"), - TERMINAL_RPAREN(5, "rparen"), - TERMINAL_LBRACE(6, "lbrace"), - TERMINAL_INPUT(7, "input"), - TERMINAL_NUMBER(8, "number"), - TERMINAL_OUTPUT(9, "output"), - TERMINAL_FILE(10, "file"), - TERMINAL_AS(11, "as"), - TERMINAL_DOT(12, "dot"), - TERMINAL_SEMI(13, "semi"), + public enum TerminalId implements TerminalIdentifier { + TERMINAL_COMPOSITE_TASK(0, "composite_task"), + TERMINAL_IN(1, "in"), + TERMINAL_IDENTIFIER(2, "identifier"), + TERMINAL_LBRACE(3, "lbrace"), + TERMINAL_COLON(4, "colon"), + TERMINAL_STEP(5, "step"), + TERMINAL_FOR(6, "for"), + TERMINAL_STRING(7, "string"), + TERMINAL_LPAREN(8, "lparen"), + TERMINAL_LSQUARE(9, "lsquare"), + TERMINAL_COMMA(10, "comma"), + TERMINAL_DOT(11, "dot"), + TERMINAL_FILE(12, "file"), + TERMINAL_RPAREN(13, "rparen"), TERMINAL_RBRACE(14, "rbrace"), - TERMINAL_COMMA(15, "comma"), - TERMINAL_COMPOSITE_TASK(16, "composite_task"), - TERMINAL_FOR(17, "for"), - TERMINAL_ASSIGN(18, "assign"), - TERMINAL_IDENTIFIER(19, "identifier"), - TERMINAL_COLON(20, "colon"), - TERMINAL_RSQUARE(21, "rsquare"); + TERMINAL_INPUT(15, "input"), + TERMINAL_RSQUARE(16, "rsquare"), + TERMINAL_SEMI(17, "semi"), + TERMINAL_OUTPUT(18, "output"), + TERMINAL_NUMBER(19, "number"), + TERMINAL_ASSIGN(20, "assign"), + TERMINAL_AS(21, "as"); private final int id; private final String string; TerminalId(int id, String string) { @@ -94,75 +97,248 @@ WdlParser(SyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; this.expressionParsers = new HashMap(); - this.first = new HashMap(); - this.follow = new HashMap(); + this.first = new HashMap(); + this.follow = new HashMap(); + this.nonterminal_rules = new HashMap>(); + this.rules = new HashMap(); ArrayList list; - this.first.put("step_input", new TerminalId[] { }); - this.first.put("_gen1", new TerminalId[] { }); - this.first.put("composite_task_entity", new TerminalId[] { }); - this.first.put("step_output_list", new TerminalId[] { }); - this.first.put("step_name", new TerminalId[] { }); - this.first.put("task_attr", new TerminalId[] { }); - this.first.put("_gen4", new TerminalId[] { }); - this.first.put("task_attr_value", new TerminalId[] { }); - this.first.put("_gen3", new TerminalId[] { }); - this.first.put("_gen7", new TerminalId[] { }); - this.first.put("_gen2", new TerminalId[] { }); - this.first.put("wdl", new TerminalId[] { }); - this.first.put("task_attrs", new TerminalId[] { }); - this.first.put("variable", new TerminalId[] { }); - this.first.put("step_output", new TerminalId[] { }); - this.first.put("step_attr", new TerminalId[] { }); - this.first.put("_gen9", new TerminalId[] { }); - this.first.put("_gen6", new TerminalId[] { }); - this.first.put("_gen5", new TerminalId[] { }); - this.first.put("step", new TerminalId[] { }); - this.first.put("wdl_entity", new TerminalId[] { }); - this.first.put("composite_task", new TerminalId[] { }); - this.first.put("_gen11", new TerminalId[] { }); - this.first.put("_gen0", new TerminalId[] { }); - this.first.put("step_input_list", new TerminalId[] { }); - this.first.put("_gen8", new TerminalId[] { }); - this.first.put("task_identifier", new TerminalId[] { }); - this.first.put("for_loop", new TerminalId[] { }); - this.first.put("_gen10", new TerminalId[] { }); - this.first.put("variable_member", new TerminalId[] { }); - this.follow.put("step_input", new TerminalId[] { }); - this.follow.put("_gen1", new TerminalId[] { }); - this.follow.put("composite_task_entity", new TerminalId[] { }); - this.follow.put("step_output_list", new TerminalId[] { }); - this.follow.put("step_name", new TerminalId[] { }); - this.follow.put("task_attr", new TerminalId[] { }); - this.follow.put("_gen4", new TerminalId[] { }); - this.follow.put("task_attr_value", new TerminalId[] { }); - this.follow.put("_gen3", new TerminalId[] { }); - this.follow.put("_gen7", new TerminalId[] { }); - this.follow.put("_gen2", new TerminalId[] { }); + String rule; + this.nonterminal_rules.put("step_output_list", new ArrayList()); + this.nonterminal_rules.put("_gen11", new ArrayList()); + this.nonterminal_rules.put("task_attr", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("composite_task_entity", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); + this.nonterminal_rules.put("_gen3", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); + this.nonterminal_rules.put("step_input", new ArrayList()); + this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("step_name", new ArrayList()); + this.nonterminal_rules.put("step", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); + this.nonterminal_rules.put("_gen9", new ArrayList()); + this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("_gen10", new ArrayList()); + this.nonterminal_rules.put("task_attr_value", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen8", new ArrayList()); + rule = "_gen11 := variable_member"; + this.nonterminal_rules.get("_gen11").add(rule); + this.rules.put(new Integer(0), rule); + rule = "_gen11 := ε"; + this.nonterminal_rules.get("_gen11").add(rule); + this.rules.put(new Integer(1), rule); + rule = "_gen2 := step _gen2"; + this.nonterminal_rules.get("_gen2").add(rule); + this.rules.put(new Integer(2), rule); + rule = "step_output_list := 'output' 'colon' _gen9 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); + this.rules.put(new Integer(3), rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); + this.rules.put(new Integer(4), rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); + this.rules.put(new Integer(5), rule); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); + this.rules.put(new Integer(6), rule); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); + this.rules.put(new Integer(7), rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); + this.rules.put(new Integer(8), rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(9), rule); + rule = "_gen3 := step_name"; + this.nonterminal_rules.get("_gen3").add(rule); + this.rules.put(new Integer(10), rule); + rule = "_gen7 := ε"; + this.nonterminal_rules.get("_gen7").add(rule); + this.rules.put(new Integer(11), rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); + this.rules.put(new Integer(12), rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(13), rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(14), rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); + this.rules.put(new Integer(15), rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; + this.nonterminal_rules.get("composite_task").add(rule); + this.rules.put(new Integer(16), rule); + rule = "_gen8 := 'comma' step_input _gen8"; + this.nonterminal_rules.get("_gen8").add(rule); + this.rules.put(new Integer(17), rule); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); + this.rules.put(new Integer(18), rule); + rule = "_gen6 := ε"; + this.nonterminal_rules.get("_gen6").add(rule); + this.rules.put(new Integer(19), rule); + rule = "_gen9 := step_output _gen10"; + this.nonterminal_rules.get("_gen9").add(rule); + this.rules.put(new Integer(20), rule); + rule = "_gen4 := step_attr _gen4"; + this.nonterminal_rules.get("_gen4").add(rule); + this.rules.put(new Integer(21), rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); + this.rules.put(new Integer(22), rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; + this.nonterminal_rules.get("step_output").add(rule); + this.rules.put(new Integer(23), rule); + rule = "_gen7 := step_input _gen8"; + this.nonterminal_rules.get("_gen7").add(rule); + this.rules.put(new Integer(24), rule); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); + this.rules.put(new Integer(25), rule); + rule = "task_attr_value := 'identifier'"; + this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(26), rule); + rule = "_gen0 := wdl_entity _gen0"; + this.nonterminal_rules.get("_gen0").add(rule); + this.rules.put(new Integer(27), rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + this.nonterminal_rules.get("task_attr").add(rule); + this.rules.put(new Integer(28), rule); + rule = "step_input_list := 'input' 'colon' _gen7 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); + this.rules.put(new Integer(29), rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); + this.rules.put(new Integer(30), rule); + rule = "composite_task_entity := step"; + this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(31), rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); + this.rules.put(new Integer(32), rule); + rule = "task_identifier := 'identifier' _gen5 -> Task( attributes=$1, name=$0 )"; + this.nonterminal_rules.get("task_identifier").add(rule); + this.rules.put(new Integer(33), rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); + this.rules.put(new Integer(34), rule); + rule = "_gen5 := task_attrs"; + this.nonterminal_rules.get("_gen5").add(rule); + this.rules.put(new Integer(35), rule); + rule = "variable := 'identifier' _gen11 -> Variable( member=$1, name=$0 )"; + this.nonterminal_rules.get("variable").add(rule); + this.rules.put(new Integer(36), rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen2 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; + this.nonterminal_rules.get("for_loop").add(rule); + this.rules.put(new Integer(37), rule); + rule = "_gen5 := ε"; + this.nonterminal_rules.get("_gen5").add(rule); + this.rules.put(new Integer(38), rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); + this.rules.put(new Integer(39), rule); + rule = "task_attrs := 'lsquare' _gen6 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); + this.rules.put(new Integer(40), rule); + rule = "_gen2 := ε"; + this.nonterminal_rules.get("_gen2").add(rule); + this.rules.put(new Integer(41), rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); + this.rules.put(new Integer(42), rule); + rule = "step := 'step' task_identifier _gen3 'lbrace' _gen4 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; + this.nonterminal_rules.get("step").add(rule); + this.rules.put(new Integer(43), rule); + rule = "_gen10 := 'comma' step_output _gen10"; + this.nonterminal_rules.get("_gen10").add(rule); + this.rules.put(new Integer(44), rule); + rule = "_gen6 := task_attr _gen6"; + this.nonterminal_rules.get("_gen6").add(rule); + this.rules.put(new Integer(45), rule); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen11", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); + this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_STEP }); + this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); + this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); + this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); + this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen11", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); this.follow.put("wdl", new TerminalId[] { }); - this.follow.put("task_attrs", new TerminalId[] { }); - this.follow.put("variable", new TerminalId[] { }); - this.follow.put("step_output", new TerminalId[] { }); - this.follow.put("step_attr", new TerminalId[] { }); - this.follow.put("_gen9", new TerminalId[] { }); - this.follow.put("_gen6", new TerminalId[] { }); - this.follow.put("_gen5", new TerminalId[] { }); - this.follow.put("step", new TerminalId[] { }); - this.follow.put("wdl_entity", new TerminalId[] { }); - this.follow.put("composite_task", new TerminalId[] { }); - this.follow.put("_gen11", new TerminalId[] { }); this.follow.put("_gen0", new TerminalId[] { }); - this.follow.put("step_input_list", new TerminalId[] { }); - this.follow.put("_gen8", new TerminalId[] { }); - this.follow.put("task_identifier", new TerminalId[] { }); - this.follow.put("for_loop", new TerminalId[] { }); - this.follow.put("_gen10", new TerminalId[] { }); - this.follow.put("variable_member", new TerminalId[] { }); + this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); } public TerminalMap getTerminalMap() { return new WdlTerminalMap(TerminalId.values()); } public ParseTree parse(TokenStream tokens) throws SyntaxError { this.tokens = tokens; + this.tokens.setSyntaxErrorFormatter(this.syntaxErrorFormatter); + this.tokens.setTerminalMap(this.getTerminalMap()); ParseTree tree = this.parse_wdl(); if (this.tokens.current() != null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); @@ -182,162 +358,204 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (22 <= terminal && terminal <= 51); } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "step_input")); + ParseTree tree = new ParseTree( new NonTerminal(22, "step_output_list")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") + )); } - if (rule == 29) { + if (rule == 3) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(3)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(3)); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse__gen9(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(3)); + tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step_output_list")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_output_list", + current, + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(3) + )); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen11() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen1")); - tree.setList("nlist"); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen11")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == 10 || current.getId() == 17) { return tree; } } if (current == null) { return tree; } - if (rule == 28) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); - tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "composite_task_entity")); + ParseTree tree = new ParseTree( new NonTerminal(24, "task_attr")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") + )); } - if (rule == 9) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); - return tree; - } - else if (rule == 34) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(28)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(28)); + tree.add(next); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task_entity", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("task_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr", + current, + Arrays.asList(this.first.get("task_attr")), + this.rules.get(28) + )); } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "step_output_list")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(25, "_gen6")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 16) { + return tree; + } + } if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } - if (rule == 27) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse__gen9(); + if (rule == 45) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen6(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); - tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output_list", current, new ArrayList())); + return tree; } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "step_name")); + ParseTree tree = new ParseTree( new NonTerminal(26, "composite_task")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") + )); } - if (rule == 18) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + if (rule == 16) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(16)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(16)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(16)); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(16)); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_name", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("composite_task")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task", + current, + Arrays.asList(this.first.get("composite_task")), + this.rules.get(16) + )); } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "task_attr")); + ParseTree tree = new ParseTree( new NonTerminal(27, "composite_task_entity")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task_entity", + Arrays.asList(this.first.get("composite_task_entity")), + this.nonterminal_rules.get("composite_task_entity") + )); } - if (rule == 44) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse_task_attr_value(); + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_for_loop(); + tree.add( subtree); + return tree; + } + else if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("composite_task_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task_entity", + current, + Arrays.asList(this.first.get("composite_task_entity")), + this.rules.get(31) + )); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen4")); + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen1")); tree.setList("nlist"); if ( current != null ) { if (current.getId() == 14) { @@ -347,440 +565,569 @@ private ParseTree parse__gen4() throws SyntaxError { if (current == null) { return tree; } - if (rule == 19) { + if (rule == 15) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen4(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "task_attr_value")); + ParseTree tree = new ParseTree( new NonTerminal(29, "step_attr")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") + )); } - if (rule == 2) { + if (rule == 39) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); - tree.add(next); - return tree; - } - else if (rule == 37) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); + subtree = this.parse_step_output_list(); + tree.add( subtree); return tree; } - else if (rule == 39) { + else if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER.id(), this.syntaxErrorFormatter); - tree.add(next); + subtree = this.parse_step_input_list(); + tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attr_value", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_attr", + current, + Arrays.asList(this.first.get("step_attr")), + this.rules.get(42) + )); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "_gen3")); + ParseTree tree = new ParseTree( new NonTerminal(30, "task_identifier")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 6) { - return tree; - } - } if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_identifier", + Arrays.asList(this.first.get("task_identifier")), + this.nonterminal_rules.get("task_identifier") + )); } - if (rule == 6) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + if (rule == 33) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("attributes", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(33)); + tree.add(next); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("task_identifier")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_identifier", + current, + Arrays.asList(this.first.get("task_identifier")), + this.rules.get(33) + )); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen7")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 13) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 26) { + if (rule == 21) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "_gen2")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 14) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(32, "task_attrs")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") + )); } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); - subtree = this.parse__gen2(); + if (rule == 40) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(40)); + tree.add(next); + subtree = this.parse__gen6(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(40)); + tree.add(next); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("task_attrs")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attrs", + current, + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(40) + )); } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "wdl")); + ParseTree tree = new ParseTree( new NonTerminal(33, "variable_member")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") + )); } - if (rule == 43) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); - tree.add( subtree); + if (rule == 18) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(18)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(18)); + tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("variable_member")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable_member", + current, + Arrays.asList(this.first.get("variable_member")), + this.rules.get(18) + )); } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "task_attrs")); + ParseTree tree = new ParseTree( new NonTerminal(34, "_gen3")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 3) { + return tree; + } + } if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } - if (rule == 36) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id(), this.syntaxErrorFormatter); - tree.add(next); - subtree = this.parse__gen6(); + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_name(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id(), this.syntaxErrorFormatter); - tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_attrs", current, new ArrayList())); + return tree; } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "variable")); + ParseTree tree = new ParseTree( new NonTerminal(35, "for_loop")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") + )); } - if (rule == 13) { + if (rule == 37) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(37)); tree.add(next); - subtree = this.parse__gen11(); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(37)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(37)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(37)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(37)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(37)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(37)); + tree.add(next); + subtree = this.parse__gen2(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(37)); + tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("for_loop")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "for_loop", + current, + Arrays.asList(this.first.get("for_loop")), + this.rules.get(37) + )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "step_output")); + ParseTree tree = new ParseTree( new NonTerminal(36, "variable")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") + )); } - if (rule == 41) { + if (rule == 36) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS.id(), this.syntaxErrorFormatter); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(36)); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse__gen11(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_output", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("variable")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable", + current, + Arrays.asList(this.first.get("variable")), + this.rules.get(36) + )); } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step_attr")); + ParseTree tree = new ParseTree( new NonTerminal(37, "step_input")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") + )); } - if (rule == 23) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); - tree.add( subtree); - return tree; - } - else if (rule == 31) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + if (rule == 6) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(6)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(6)); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_attr", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step_input")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_input", + current, + Arrays.asList(this.first.get("step_input")), + this.rules.get(6) + )); } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen9")); + ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 13) { + if (current.getId() == 17) { return tree; } } if (current == null) { return tree; } - if (rule == 11) { + if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen6")); + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen2")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 21) { + if (current.getId() == 14) { return tree; } } if (current == null) { return tree; } - if (rule == 1) { + if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); + subtree = this.parse_step(); tree.add( subtree); - subtree = this.parse__gen6(); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen5")); + ParseTree tree = new ParseTree( new NonTerminal(40, "wdl")); tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 7) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("wdl")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "wdl", + current, + Arrays.asList(this.first.get("wdl")), + this.rules.get(7) + )); + } + private ParseTree parse__gen0() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "_gen0")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 11) { + if (current.getId() == -1) { return tree; } } if (current == null) { return tree; } - if (rule == 32) { + if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + subtree = this.parse_wdl_entity(); + tree.add( subtree); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } + private ParseTree parse_step_name() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "step_name")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") + )); + } + if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(32)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(32)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_name")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_name", + current, + Arrays.asList(this.first.get("step_name")), + this.rules.get(32) + )); + } private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "step")); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "step")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") + )); } - if (rule == 22) { + if (rule == 43) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 4); parameters.put("task", 1); parameters.put("name", 2); tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(43)); tree.add(next); subtree = this.parse_task_identifier(); tree.add( subtree); subtree = this.parse__gen3(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(43)); tree.add(next); subtree = this.parse__gen4(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(43)); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step", + current, + Arrays.asList(this.first.get("step")), + this.rules.get(43) + )); } - private ParseTree parse_wdl_entity() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "wdl_entity")); - tree.setList(null); - if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); - } - if (rule == 3) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); - tree.add( subtree); - return tree; - } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("wdl_entity", current, new ArrayList())); - } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "composite_task")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "step_output")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") + )); } - if (rule == 17) { + if (rule == 23) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK.id(), this.syntaxErrorFormatter); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(23)); tree.add(next); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(23)); tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("composite_task", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step_output")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_output", + current, + Arrays.asList(this.first.get("step_output")), + this.rules.get(23) + )); } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "_gen11")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "wdl_entity")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 15 || current.getId() == 13) { - return tree; - } - } if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "wdl_entity", + Arrays.asList(this.first.get("wdl_entity")), + this.nonterminal_rules.get("wdl_entity") + )); } - if (rule == 42) { + if (rule == 22) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("wdl_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "wdl_entity", + current, + Arrays.asList(this.first.get("wdl_entity")), + this.rules.get(22) + )); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "_gen0")); - tree.setList("nlist"); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "_gen9")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 17) { return tree; } } if (current == null) { return tree; } - if (rule == 24) { + if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } @@ -790,167 +1137,155 @@ private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "step_input_list")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "step_input_list")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") + )); } - if (rule == 10) { + if (rule == 29) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("inputs", 2); tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(29)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(29)); tree.add(next); subtree = this.parse__gen7(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(29)); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("step_input_list", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("step_input_list")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_input_list", + current, + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(29) + )); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "_gen8")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "_gen10")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 13) { + if (current.getId() == 17) { return tree; } } if (current == null) { return tree; } - if (rule == 25) { + if (rule == 44) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen10", this.rules.get(44)); tree.add(next); tree.setListSeparator(next); - subtree = this.parse_step_input(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "task_identifier")); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "task_attr_value")); tree.setList(null); if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") + )); } - if (rule == 7) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + if (rule == 13) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(13)); tree.add(next); - subtree = this.parse__gen5(); - tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("task_identifier", current, new ArrayList())); - } - private ParseTree parse_for_loop() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "for_loop")); - tree.setList(null); - if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); - } - if (rule == 14) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id(), this.syntaxErrorFormatter); + else if (rule == 14) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(14)); tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id(), this.syntaxErrorFormatter); + return tree; + } + else if (rule == 26) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(26)); tree.add(next); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("for_loop", current, new ArrayList())); + List terminals = Arrays.asList(this.first.get("task_attr_value")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr_value", + current, + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(26) + )); } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen10")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen5")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 13) { + if (current.getId() == 21) { return tree; } } if (current == null) { return tree; } - if (rule == 8) { + if (rule == 35) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id(), this.syntaxErrorFormatter); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(51, "variable_member")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(51, "_gen8")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 17) { + return tree; + } + } if (current == null) { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(stack[1].getMethodName(), null)); + return tree; } - if (rule == 33) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT.id(), this.syntaxErrorFormatter); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id(), this.syntaxErrorFormatter); + if (rule == 17) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen8", this.rules.get(17)); tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen8(); + tree.add( subtree); return tree; } - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol("variable_member", current, new ArrayList())); + return tree; } } diff --git a/wdl/WdlSourceCode.java b/wdl/WdlSourceCode.java index c47c76e..a50d875 100644 --- a/wdl/WdlSourceCode.java +++ b/wdl/WdlSourceCode.java @@ -53,9 +53,12 @@ public void advance(int amount) { String str = this.contents.substring(0, amount); for ( byte b : str.getBytes() ) { if ( b == (byte) '\n' || b == (byte) '\r' ) { + this.lines.add(this.currentLine.toString()); + this.currentLine = new StringBuilder(); this.line++; this.col = 1; } else { + this.currentLine.append((char)b); this.col++; } } @@ -79,10 +82,10 @@ public int getColumn() { } public String getLine(int lineno) { - return null; // TODO + return this.lines.get(lineno-1); } public List getLines() { - return null; // TODO + return this.lines; } } diff --git a/wdl/WdlSyntaxErrorFormatter.java b/wdl/WdlSyntaxErrorFormatter.java index 10e462c..57722dc 100644 --- a/wdl/WdlSyntaxErrorFormatter.java +++ b/wdl/WdlSyntaxErrorFormatter.java @@ -2,27 +2,56 @@ import java.util.List; class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { - private TerminalMap map; - public void setTerminalMap(TerminalMap map) { - this.map = map; + private SourceCode code; + public void setSourceCode(SourceCode code) { + this.code = code; } - public String unexpected_eof(String method, List expected) { - return "Error: unexpected end of file"; + + public String unexpected_eof(String method, List expected, List nt_rules) { + ArrayList expected_terminals = new ArrayList(); + if ( expected != null && expected.size() > 0 ) { + for ( TerminalIdentifier e : expected ) { + expected_terminals.add(e.string()); + } + } + return "Unexpected end of file when parsing " + method + "\n\nExpecting one of: " + Utility.join(expected_terminals, ", ") + "\nPossible rules:\n" + Utility.join(nt_rules, "\n"); } + public String excess_tokens(String method, Terminal terminal) { - return "Finished parsing without consuming all tokens."; + String msg = "Finished parsing without consuming all tokens"; + msg += "\nLocation: " + terminal.getResource() + " @ line " + terminal.getLine() + ", column " + terminal.getColumn(); + return msg; } - public String unexpected_symbol(String method, Terminal actual, List expected) { - ArrayList expected_terminals = new ArrayList(); - for ( Integer e : expected ) { - expected_terminals.add(this.map.get(e.intValue())); + + public String unexpected_symbol(String method, Terminal actual, List expected, String rule) { + String msg = "Unexpected symbol " + actual.getTerminalStr(); + + if ( expected != null && expected.size() > 0 ) { + ArrayList expected_terminals = new ArrayList(); + for ( TerminalIdentifier e : expected ) { + expected_terminals.add(e.string()); + } + msg += ". Expecting " + Utility.join(expected_terminals, ", ") + "."; } - return "Unexpected symbol when parsing " + method + ". Expected " + Utility.join(expected_terminals, ", ") + ", got " + actual.getTerminalStr() + "."; + + msg += "\nRule: " + rule; + msg += "\nLocation: " + actual.getResource() + " @ line " + actual.getLine() + ", column " + actual.getColumn() + ":\n\n"; + msg += code.getLine(actual.getLine()) + "\n"; + msg += Utility.getIndentString(actual.getColumn()-1) + "^\n"; + return msg; } - public String no_more_tokens(String method, int expecting) { - return "No more tokens. Expecting " + this.map.get(expecting); + + public String no_more_tokens(String method, TerminalIdentifier expecting, Terminal last) { + String lastLine = this.code.getLine(last.getLine()); + return "No more tokens when parsing " + method + "\nExpecting: " + expecting.string() + "\nLocation: " + last.getResource() + " @ line " + last.getLine() + ", column " + last.getColumn() + ":\n\n" + lastLine + "\n" + Utility.getIndentString(last.getColumn()-1) + "^\n"; } + public String invalid_terminal(String method, Terminal invalid) { return "Invalid symbol ID: "+invalid.getId()+" ("+invalid.getTerminalStr()+")"; } + + public String missing_version(Terminal task_name) { + return "Version information missing for task " + task_name.getSourceString() + "\nLocation: " + task_name.getResource() + " @ line " + task_name.getLine() + ", column " + task_name.getColumn() + ":\n\n" + this.code.getLine(task_name.getLine()) + "\n" + Utility.getIndentString(task_name.getColumn()-1) + "^\n"; + } + } diff --git a/wdl/error.wdl b/wdl/error.wdl deleted file mode 100644 index 5ebb85f..0000000 --- a/wdl/error.wdl +++ /dev/null @@ -1,27 +0,0 @@ -/* inputs: - * 1) MutSigPreprocess.{individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile} - * 2) ProcessCoverageForMutSig has no variables. All inputs come from prior step. - * 3) MutSigRun.{individual_set_id, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, jobcount} - */ - -composite_task MutSig { - - step MutSigPreprocess[verson=86] { - output: File("coverage.prepare.txt") as coverage_prepare_file, - File("patients.txt") as patient_list,, - File("${individual_set_id}.maf") as mutation_list, - File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; - } - - step ProcessCoverageForMutSig[version=75] { - input: coverage=coverage_prepare_file, patients=patient_list, mutations=mutation_list; - output: File("coverage.mat") as coverage_file, - File("mutcategs.txt") as category_file; - } - - step MutSigRun[version=157] as MutSig { - input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file=category_file, mutation_preprocessing_report=foobar; - output: File("bargraphs.png") as graphs; - } - -} From 2d90acb7feb74136ac84d8ee45a402751fd69aee Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 13 Aug 2012 09:09:11 -0400 Subject: [PATCH 030/140] interface fixes and some documentation --- wdl/CompositeTask.java | 10 ++++--- wdl/README.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++- wdl/WdlMain.java | 28 +++++++++++++++--- wdl/simple.wdl | 1 + 4 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 wdl/simple.wdl diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 479ca8e..604f91f 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -43,10 +43,12 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { boolean version_found = false; - for ( AstNode task_attr : task_attrs ) { - Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); - if ( key.getSourceString().equals("version") ) { - version_found = true; + if ( task_attrs != null ) { + for ( AstNode task_attr : task_attrs ) { + Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); + if ( key.getSourceString().equals("version") ) { + version_found = true; + } } } diff --git a/wdl/README.md b/wdl/README.md index 24c6a6d..844dc35 100644 --- a/wdl/README.md +++ b/wdl/README.md @@ -6,8 +6,86 @@ There are two example .wdl files in this directory that parse: * MutSig.wdl * CopyNumberQC.wdl -To get an AbstractSyntaxTree (Ast) from a source file: +From Java code, the main interface is the CompositeTask, which can be used in this example to acquire the name of each task: +```java +CompositeTask wdl = new CompositeTask(new File(args[0])); +Map steps = wdl.getSteps(); +for ( Map.Entry entry : steps.entrySet() ) { + System.out.println("Step: " + entry.getKey()); +} ``` +To extract parse tree, and abstract syntax tree information from the command line: + +``` +$ javac *.java +$ cat simple.wdl +composite_task x {step y[version=0] {}} +$ java WdlMain simple.wdl parsetree +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen5: + (task_attrs: + lsquare, + (_gen6: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen6: ) + ), + rsquare + ) + ) + ), + (_gen3: ), + lbrace, + (_gen4: ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) +$ java WdlMain simple.wdl ast +(CompositeTask: + body=[ + (Step: + body=[], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + name=identifier +) +$ java WdlMain simple.wdl nodes +Step: y ``` diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index 3b73bea..abe52ac 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -4,14 +4,34 @@ import java.util.Map; class WdlMain { + + public static void usage() { + System.err.println("Usage: java ParserMain <.wdl file> "); + System.exit(-1); + } + public static void main(String[] args) { + if (args.length < 2) { + usage(); + } + try { CompositeTask wdl = new CompositeTask(new File(args[0])); - Ast ast = wdl.getAst(); - Map steps = wdl.getSteps(); - for ( Map.Entry entry : steps.entrySet() ) { - System.out.println("--- Step " + entry.getKey()); + + if ( args[1].equals("ast") ) { + Ast ast = wdl.getAst(); + System.out.println(ast.toPrettyString()); + } else if ( args[1].equals("parsetree") ) { + ParseTree tree = wdl.getParseTree(); + System.out.println(tree.toPrettyString()); + } else if ( args[1].equals("nodes") ) { + Map steps = wdl.getSteps(); + for ( Map.Entry entry : steps.entrySet() ) { + System.out.println("Step: " + entry.getKey()); + } + } else { + usage(); } } catch (IOException error) { System.err.println(error); diff --git a/wdl/simple.wdl b/wdl/simple.wdl new file mode 100644 index 0000000..195e03f --- /dev/null +++ b/wdl/simple.wdl @@ -0,0 +1 @@ +composite_task x {step y[version=0] {}} From 4ff3d11a84d7840cc2292679574c96c7dfac5eb0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 17 Aug 2012 16:32:44 -0400 Subject: [PATCH 031/140] removing org.json --- wdl/org/json/CDL.java | 279 ------- wdl/org/json/Cookie.java | 169 ----- wdl/org/json/CookieList.java | 90 --- wdl/org/json/HTTP.java | 163 ---- wdl/org/json/HTTPTokener.java | 77 -- wdl/org/json/JSONArray.java | 906 ---------------------- wdl/org/json/JSONException.java | 28 - wdl/org/json/JSONML.java | 467 ------------ wdl/org/json/JSONObject.java | 1593 --------------------------------------- wdl/org/json/JSONString.java | 18 - wdl/org/json/JSONStringer.java | 78 -- wdl/org/json/JSONTokener.java | 446 ----------- wdl/org/json/JSONWriter.java | 327 -------- wdl/org/json/XML.java | 508 ------------- wdl/org/json/XMLTokener.java | 365 --------- 15 files changed, 5514 deletions(-) delete mode 100755 wdl/org/json/CDL.java delete mode 100755 wdl/org/json/Cookie.java delete mode 100755 wdl/org/json/CookieList.java delete mode 100755 wdl/org/json/HTTP.java delete mode 100755 wdl/org/json/HTTPTokener.java delete mode 100644 wdl/org/json/JSONArray.java delete mode 100755 wdl/org/json/JSONException.java delete mode 100755 wdl/org/json/JSONML.java delete mode 100755 wdl/org/json/JSONObject.java delete mode 100755 wdl/org/json/JSONString.java delete mode 100755 wdl/org/json/JSONStringer.java delete mode 100644 wdl/org/json/JSONTokener.java delete mode 100755 wdl/org/json/JSONWriter.java delete mode 100755 wdl/org/json/XML.java delete mode 100755 wdl/org/json/XMLTokener.java diff --git a/wdl/org/json/CDL.java b/wdl/org/json/CDL.java deleted file mode 100755 index fd5d476..0000000 --- a/wdl/org/json/CDL.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * This provides static methods to convert comma delimited text into a - * JSONArray, and to covert a JSONArray into comma delimited text. Comma - * delimited text is a very popular format for data interchange. It is - * understood by most database, spreadsheet, and organizer programs. - *

- * Each row of text represents a row in a table or a data record. Each row - * ends with a NEWLINE character. Each row contains one or more values. - * Values are separated by commas. A value can contain any character except - * for comma, unless is is wrapped in single quotes or double quotes. - *

- * The first row usually contains the names of the columns. - *

- * A comma delimited list can be converted into a JSONArray of JSONObjects. - * The names for the elements in the JSONObjects can be taken from the names - * in the first row. - * @author JSON.org - * @version 2010-12-24 - */ -public class CDL { - - /** - * Get the next value. The value can be wrapped in quotes. The value can - * be empty. - * @param x A JSONTokener of the source text. - * @return The value string, or null if empty. - * @throws JSONException if the quoted string is badly formed. - */ - private static String getValue(JSONTokener x) throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = x.next(); - } while (c == ' ' || c == '\t'); - switch (c) { - case 0: - return null; - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = x.next(); - if (c == q) { - break; - } - if (c == 0 || c == '\n' || c == '\r') { - throw x.syntaxError("Missing close quote '" + q + "'."); - } - sb.append(c); - } - return sb.toString(); - case ',': - x.back(); - return ""; - default: - x.back(); - return x.nextTo(','); - } - } - - /** - * Produce a JSONArray of strings from a row of comma delimited values. - * @param x A JSONTokener of the source text. - * @return A JSONArray of strings. - * @throws JSONException - */ - public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { - JSONArray ja = new JSONArray(); - for (;;) { - String value = getValue(x); - char c = x.next(); - if (value == null || - (ja.length() == 0 && value.length() == 0 && c != ',')) { - return null; - } - ja.put(value); - for (;;) { - if (c == ',') { - break; - } - if (c != ' ') { - if (c == '\n' || c == '\r' || c == 0) { - return ja; - } - throw x.syntaxError("Bad character '" + c + "' (" + - (int)c + ")."); - } - c = x.next(); - } - } - } - - /** - * Produce a JSONObject from a row of comma delimited text, using a - * parallel JSONArray of strings to provides the names of the elements. - * @param names A JSONArray of names. This is commonly obtained from the - * first row of a comma delimited text file using the rowToJSONArray - * method. - * @param x A JSONTokener of the source text. - * @return A JSONObject combining the names and values. - * @throws JSONException - */ - public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) - throws JSONException { - JSONArray ja = rowToJSONArray(x); - return ja != null ? ja.toJSONObject(names) : null; - } - - /** - * Produce a comma delimited text row from a JSONArray. Values containing - * the comma character will be quoted. Troublesome characters may be - * removed. - * @param ja A JSONArray of strings. - * @return A string ending in NEWLINE. - */ - public static String rowToString(JSONArray ja) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - if (i > 0) { - sb.append(','); - } - Object object = ja.opt(i); - if (object != null) { - String string = object.toString(); - if (string.length() > 0 && (string.indexOf(',') >= 0 || - string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || - string.indexOf(0) >= 0 || string.charAt(0) == '"')) { - sb.append('"'); - int length = string.length(); - for (int j = 0; j < length; j += 1) { - char c = string.charAt(j); - if (c >= ' ' && c != '"') { - sb.append(c); - } - } - sb.append('"'); - } else { - sb.append(string); - } - } - } - sb.append('\n'); - return sb.toString(); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param x The JSONTokener containing the comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONTokener x) throws JSONException { - return toJSONArray(rowToJSONArray(x), x); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, String string) - throws JSONException { - return toJSONArray(names, new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param x A JSONTokener of the source text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, JSONTokener x) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (;;) { - JSONObject jo = rowToJSONObject(names, x); - if (jo == null) { - break; - } - ja.put(jo); - } - if (ja.length() == 0) { - return null; - } - return ja; - } - - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects. The - * first row will be a list of names obtained by inspecting the first - * JSONObject. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - JSONObject jo = ja.optJSONObject(0); - if (jo != null) { - JSONArray names = jo.names(); - if (names != null) { - return rowToString(names) + toString(names, ja); - } - } - return null; - } - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects using - * a provided list of names. The list of names is not included in the - * output. - * @param names A JSONArray of strings. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray names, JSONArray ja) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - JSONObject jo = ja.optJSONObject(i); - if (jo != null) { - sb.append(rowToString(jo.toJSONArray(names))); - } - } - return sb.toString(); - } -} diff --git a/wdl/org/json/Cookie.java b/wdl/org/json/Cookie.java deleted file mode 100755 index 9cf5ce2..0000000 --- a/wdl/org/json/Cookie.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * Convert a web browser cookie specification to a JSONObject and back. - * JSON and Cookies are both notations for name/value pairs. - * @author JSON.org - * @version 2010-12-24 - */ -public class Cookie { - - /** - * Produce a copy of a string in which the characters '+', '%', '=', ';' - * and control characters are replaced with "%hh". This is a gentle form - * of URL encoding, attempting to cause as little distortion to the - * string as possible. The characters '=' and ';' are meta characters in - * cookies. By convention, they are escaped using the URL-encoding. This is - * only a convention, not a standard. Often, cookies are expected to have - * encoded values. We encode '=' and ';' because we must. We encode '%' and - * '+' because they are meta characters in URL encoding. - * @param string The source string. - * @return The escaped result. - */ - public static String escape(String string) { - char c; - String s = string.trim(); - StringBuffer sb = new StringBuffer(); - int length = s.length(); - for (int i = 0; i < length; i += 1) { - c = s.charAt(i); - if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { - sb.append('%'); - sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); - sb.append(Character.forDigit((char)(c & 0x0f), 16)); - } else { - sb.append(c); - } - } - return sb.toString(); - } - - - /** - * Convert a cookie specification string into a JSONObject. The string - * will contain a name value pair separated by '='. The name and the value - * will be unescaped, possibly converting '+' and '%' sequences. The - * cookie properties may follow, separated by ';', also represented as - * name=value (except the secure property, which does not have a value). - * The name will be stored under the key "name", and the value will be - * stored under the key "value". This method does not do checking or - * validation of the parameters. It only converts the cookie string into - * a JSONObject. - * @param string The cookie specification string. - * @return A JSONObject containing "name", "value", and possibly other - * members. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - String name; - JSONObject jo = new JSONObject(); - Object value; - JSONTokener x = new JSONTokener(string); - jo.put("name", x.nextTo('=')); - x.next('='); - jo.put("value", x.nextTo(';')); - x.next(); - while (x.more()) { - name = unescape(x.nextTo("=;")); - if (x.next() != '=') { - if (name.equals("secure")) { - value = Boolean.TRUE; - } else { - throw x.syntaxError("Missing '=' in cookie parameter."); - } - } else { - value = unescape(x.nextTo(';')); - x.next(); - } - jo.put(name, value); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie specification string. The JSONObject - * must contain "name" and "value" members. - * If the JSONObject contains "expires", "domain", "path", or "secure" - * members, they will be appended to the cookie specification string. - * All other members are ignored. - * @param jo A JSONObject - * @return A cookie specification string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - - sb.append(escape(jo.getString("name"))); - sb.append("="); - sb.append(escape(jo.getString("value"))); - if (jo.has("expires")) { - sb.append(";expires="); - sb.append(jo.getString("expires")); - } - if (jo.has("domain")) { - sb.append(";domain="); - sb.append(escape(jo.getString("domain"))); - } - if (jo.has("path")) { - sb.append(";path="); - sb.append(escape(jo.getString("path"))); - } - if (jo.optBoolean("secure")) { - sb.append(";secure"); - } - return sb.toString(); - } - - /** - * Convert %hh sequences to single characters, and - * convert plus to space. - * @param string A string that may contain - * + (plus) and - * %hh sequences. - * @return The unescaped string. - */ - public static String unescape(String string) { - int length = string.length(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; ++i) { - char c = string.charAt(i); - if (c == '+') { - c = ' '; - } else if (c == '%' && i + 2 < length) { - int d = JSONTokener.dehexchar(string.charAt(i + 1)); - int e = JSONTokener.dehexchar(string.charAt(i + 2)); - if (d >= 0 && e >= 0) { - c = (char)(d * 16 + e); - i += 2; - } - } - sb.append(c); - } - return sb.toString(); - } -} diff --git a/wdl/org/json/CookieList.java b/wdl/org/json/CookieList.java deleted file mode 100755 index 7f4fe07..0000000 --- a/wdl/org/json/CookieList.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert a web browser cookie list string to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class CookieList { - - /** - * Convert a cookie list into a JSONObject. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The names and the values - * will be unescaped, possibly converting '+' and '%' sequences. - * - * To add a cookie to a cooklist, - * cookielistJSONObject.put(cookieJSONObject.getString("name"), - * cookieJSONObject.getString("value")); - * @param string A cookie list string - * @return A JSONObject - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - JSONTokener x = new JSONTokener(string); - while (x.more()) { - String name = Cookie.unescape(x.nextTo('=')); - x.next('='); - jo.put(name, Cookie.unescape(x.nextTo(';'))); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie list. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The characters '%', '+', '=', and ';' - * in the names and values are replaced by "%hh". - * @param jo A JSONObject - * @return A cookie list string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - boolean b = false; - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!jo.isNull(string)) { - if (b) { - sb.append(';'); - } - sb.append(Cookie.escape(string)); - sb.append("="); - sb.append(Cookie.escape(jo.getString(string))); - b = true; - } - } - return sb.toString(); - } -} diff --git a/wdl/org/json/HTTP.java b/wdl/org/json/HTTP.java deleted file mode 100755 index 43d04a8..0000000 --- a/wdl/org/json/HTTP.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert an HTTP header to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTP { - - /** Carriage return/line feed. */ - public static final String CRLF = "\r\n"; - - /** - * Convert an HTTP header string into a JSONObject. It can be a request - * header or a response header. A request header will contain - *

{
-     *    Method: "POST" (for example),
-     *    "Request-URI": "/" (for example),
-     *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
- * A response header will contain - *
{
-     *    "HTTP-Version": "HTTP/1.1" (for example),
-     *    "Status-Code": "200" (for example),
-     *    "Reason-Phrase": "OK" (for example)
-     * }
- * In addition, the other parameters in the header will be captured, using - * the HTTP field names as JSON names, so that
-     *    Date: Sun, 26 May 2002 18:06:04 GMT
-     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
-     *    Cache-Control: no-cache
- * become - *
{...
-     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
-     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
-     *    "Cache-Control": "no-cache",
-     * ...}
- * It does no further checking or conversion. It does not parse dates. - * It does not do '%' transforms on URLs. - * @param string An HTTP header string. - * @return A JSONObject containing the elements and attributes - * of the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - HTTPTokener x = new HTTPTokener(string); - String token; - - token = x.nextToken(); - if (token.toUpperCase().startsWith("HTTP")) { - -// Response - - jo.put("HTTP-Version", token); - jo.put("Status-Code", x.nextToken()); - jo.put("Reason-Phrase", x.nextTo('\0')); - x.next(); - - } else { - -// Request - - jo.put("Method", token); - jo.put("Request-URI", x.nextToken()); - jo.put("HTTP-Version", x.nextToken()); - } - -// Fields - - while (x.more()) { - String name = x.nextTo(':'); - x.next(':'); - jo.put(name, x.nextTo('\0')); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into an HTTP header. A request header must contain - *
{
-     *    Method: "POST" (for example),
-     *    "Request-URI": "/" (for example),
-     *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
- * A response header must contain - *
{
-     *    "HTTP-Version": "HTTP/1.1" (for example),
-     *    "Status-Code": "200" (for example),
-     *    "Reason-Phrase": "OK" (for example)
-     * }
- * Any other members of the JSONObject will be output as HTTP fields. - * The result will end with two CRLF pairs. - * @param jo A JSONObject - * @return An HTTP header string. - * @throws JSONException if the object does not contain enough - * information. - */ - public static String toString(JSONObject jo) throws JSONException { - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { - sb.append(jo.getString("HTTP-Version")); - sb.append(' '); - sb.append(jo.getString("Status-Code")); - sb.append(' '); - sb.append(jo.getString("Reason-Phrase")); - } else if (jo.has("Method") && jo.has("Request-URI")) { - sb.append(jo.getString("Method")); - sb.append(' '); - sb.append('"'); - sb.append(jo.getString("Request-URI")); - sb.append('"'); - sb.append(' '); - sb.append(jo.getString("HTTP-Version")); - } else { - throw new JSONException("Not enough material for an HTTP header."); - } - sb.append(CRLF); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && - !"Reason-Phrase".equals(string) && !"Method".equals(string) && - !"Request-URI".equals(string) && !jo.isNull(string)) { - sb.append(string); - sb.append(": "); - sb.append(jo.getString(string)); - sb.append(CRLF); - } - } - sb.append(CRLF); - return sb.toString(); - } -} diff --git a/wdl/org/json/HTTPTokener.java b/wdl/org/json/HTTPTokener.java deleted file mode 100755 index f62b3d5..0000000 --- a/wdl/org/json/HTTPTokener.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The HTTPTokener extends the JSONTokener to provide additional methods - * for the parsing of HTTP headers. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTPTokener extends JSONTokener { - - /** - * Construct an HTTPTokener from a string. - * @param string A source string. - */ - public HTTPTokener(String string) { - super(string); - } - - - /** - * Get the next token or string. This is used in parsing HTTP headers. - * @throws JSONException - * @return A String. - */ - public String nextToken() throws JSONException { - char c; - char q; - StringBuffer sb = new StringBuffer(); - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == '"' || c == '\'') { - q = c; - for (;;) { - c = next(); - if (c < ' ') { - throw syntaxError("Unterminated string."); - } - if (c == q) { - return sb.toString(); - } - sb.append(c); - } - } - for (;;) { - if (c == 0 || Character.isWhitespace(c)) { - return sb.toString(); - } - sb.append(c); - c = next(); - } - } -} diff --git a/wdl/org/json/JSONArray.java b/wdl/org/json/JSONArray.java deleted file mode 100644 index 71c277a..0000000 --- a/wdl/org/json/JSONArray.java +++ /dev/null @@ -1,906 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -/** - * A JSONArray is an ordered sequence of values. Its external text form is a - * string wrapped in square brackets with commas separating the values. The - * internal form is an object having get and opt - * methods for accessing the values by index, and put methods for - * adding or replacing values. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the - * JSONObject.NULL object. - *

- * The constructor can convert a JSON text into a Java object. The - * toString method converts to JSON text. - *

- * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

- * The generic get() and opt() methods return an - * object which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. - *

- * The texts produced by the toString methods strictly conform to - * JSON syntax rules. The constructors are more forgiving in the texts they will - * accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing bracket.
  • - *
  • The null value will be inserted when there is , - *  (comma) elision.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
  • - *
  • Values can be separated by ; (semicolon) as - * well as by , (comma).
  • - *
- * - * @author JSON.org - * @version 2012-04-20 - */ -public class JSONArray { - - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * @param x A JSONTokener - * @throws JSONException If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); - } else { - x.back(); - this.myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); - } - } - } - } - - - /** - * Construct a JSONArray from a source JSON text. - * @param source A string that begins with - * [ (left bracket) - * and ends with ] (right bracket). - * @throws JSONException If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONArray from a Collection. - * @param collection A Collection. - */ - public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { - Iterator iter = collection.iterator(); - while (iter.hasNext()) { - this.myArrayList.add(JSONObject.wrap(iter.next())); - } - } - } - - - /** - * Construct a JSONArray from an array - * @throws JSONException If not an array. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( -"JSONArray initial value should be a string or collection or array."); - } - } - - - /** - * Get the object value associated with an index. - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with an index. - * The string values "true" and "false" are converted to boolean. - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException If there is no value for the index or if the - * value is not convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - - /** - * Get the double value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the int value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the JSONArray associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException If there is no value for the index. or if the - * value is not a JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject associated with an index. - * @param index subscript - * @return A JSONObject value. - * @throws JSONException If there is no value for the index or if the - * value is not a JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the string associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - - /** - * Determine if the value is null. - * @param index The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. - * Warning: This method assumes that the data structure is acyclical. - * @param separator A string that will be inserted between the elements. - * @return a string. - * @throws JSONException If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - - /** - * Get the optional object value associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return An object value, or null if there is no - * object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) - ? null - : this.myArrayList.get(index); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns false if there is no value at that index, - * or if the value is not Boolean.TRUE or the String "true". - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns the defaultValue if there is no value at that index or if - * it is not a Boolean or the String "true" or "false" (case insensitive). - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional double value associated with an index. - * NaN is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.NaN); - } - - - /** - * Get the optional double value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index subscript - * @param defaultValue The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional int value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public int optInt(int index) { - return this.optInt(index, 0); - } - - - /** - * Get the optional int value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - try { - return this.getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional JSONArray associated with an index. - * @param index subscript - * @return A JSONArray value, or null if the index has no value, - * or if the value is not a JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get the optional JSONObject associated with an index. - * Null is returned if the key is not found, or null if the index has - * no value, or if the value is not a JSONObject. - * - * @param index The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject)o : null; - } - - - /** - * Get the optional long value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public long optLong(int index) { - return this.optLong(index, 0); - } - - - /** - * Get the optional long value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional string value associated with an index. It returns an - * empty string if there is no value at that index. If the value - * is not a string and is not null, then it is coverted to a string. - * - * @param index The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - - /** - * Get the optional string associated with an index. - * The defaultValue is returned if the key is not found. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) - ? defaultValue : object - .toString(); - } - - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - this.put(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param value A Collection value. - * @return this. - */ - public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; - } - - - /** - * Append a double value. This increases the array's length by one. - * - * @param value A double value. - * @throws JSONException if the value is not finite. - * @return this. - */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); - JSONObject.testValidity(d); - this.put(d); - return this; - } - - - /** - * Append an int value. This increases the array's length by one. - * - * @param value An int value. - * @return this. - */ - public JSONArray put(int value) { - this.put(new Integer(value)); - return this; - } - - - /** - * Append an long value. This increases the array's length by one. - * - * @param value A long value. - * @return this. - */ - public JSONArray put(long value) { - this.put(new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject which is produced from a Map. - * @param value A Map value. - * @return this. - */ - public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; - } - - - /** - * Append an object value. This increases the array's length by one. - * @param value An object value. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - */ - public JSONArray put(Object value) { - this.myArrayList.add(value); - return this; - } - - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value A boolean value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param index The subscript. - * @param value A Collection value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; - } - - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A double value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, double value) throws JSONException { - this.put(index, new Double(value)); - return this; - } - - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value An int value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - this.put(index, new Integer(value)); - return this; - } - - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A long value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - this.put(index, new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject that is produced from a Map. - * @param index The subscript. - * @param value The Map value. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Object value) throws JSONException { - JSONObject.testValidity(value); - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - this.myArrayList.set(index, value); - } else { - while (index != this.length()) { - this.put(JSONObject.NULL); - } - this.put(value); - } - return this; - } - - - /** - * Remove an index and close the hole. - * @param index The index of the element to be removed. - * @return The value that was associated with the index, - * or null if there was no value. - */ - public Object remove(int index) { - Object o = this.opt(index); - this.myArrayList.remove(index); - return o; - } - - - /** - * Produce a JSONObject by combining a JSONArray of names with the values - * of this JSONArray. - * @param names A JSONArray containing a list of key strings. These will be - * paired with the values. - * @return A JSONObject, or null if there are no names or if this JSONArray - * has no values. - * @throws JSONException If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { - return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - - /** - * Make a JSON text of this JSONArray. For compactness, no - * unnecessary whitespace is added. If it is not possible to produce a - * syntactically correct JSON text then null will be returned instead. This - * could occur if the array contains an invalid number. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, transmittable - * representation of the array. - */ - public String toString() { - try { - return '[' + this.join(",") + ']'; - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONArray. - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with [ (left bracket) and ending - * with ] (right bracket). - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indention of the top level. - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - int length = this.length(); - writer.write('['); - - if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), - indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, this.myArrayList.get(i), - indentFactor, newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); - } - } -} diff --git a/wdl/org/json/JSONException.java b/wdl/org/json/JSONException.java deleted file mode 100755 index 289b602..0000000 --- a/wdl/org/json/JSONException.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.json; - -/** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * @author JSON.org - * @version 2010-12-24 - */ -public class JSONException extends Exception { - private static final long serialVersionUID = 0; - private Throwable cause; - - /** - * Constructs a JSONException with an explanatory message. - * @param message Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } - - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } - - public Throwable getCause() { - return this.cause; - } -} diff --git a/wdl/org/json/JSONML.java b/wdl/org/json/JSONML.java deleted file mode 100755 index f29ee72..0000000 --- a/wdl/org/json/JSONML.java +++ /dev/null @@ -1,467 +0,0 @@ -package org.json; - -/* -Copyright (c) 2008 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONArray or - * JSONObject, and to covert a JSONArray or JSONObject into an XML text using - * the JsonML transform. - * - * @author JSON.org - * @version 2012-03-28 - */ -public class JSONML { - - /** - * Parse XML values and store them in a JSONArray. - * @param x The XMLTokener containing the source string. - * @param arrayForm true if array form, false if object form. - * @param ja The JSONArray that is containing the current tag or null - * if we are at the outermost level. - * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException - */ - private static Object parse( - XMLTokener x, - boolean arrayForm, - JSONArray ja - ) throws JSONException { - String attribute; - char c; - String closeTag = null; - int i; - JSONArray newja = null; - JSONObject newjo = null; - Object token; - String tagName = null; - -// Test for and skip past these forms: -// -// -// -// - - while (true) { - if (!x.more()) { - throw x.syntaxError("Bad XML"); - } - token = x.nextContent(); - if (token == XML.LT) { - token = x.nextToken(); - if (token instanceof Character) { - if (token == XML.SLASH) { - -// Close tag "); - } else { - x.back(); - } - } else if (c == '[') { - token = x.nextToken(); - if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { - ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); - } - } else { - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - } - } else if (token == XML.QUEST) { - -// "); - } else { - throw x.syntaxError("Misshaped tag"); - } - -// Open tag < - - } else { - if (!(token instanceof String)) { - throw x.syntaxError("Bad tagName '" + token + "'."); - } - tagName = (String)token; - newja = new JSONArray(); - newjo = new JSONObject(); - if (arrayForm) { - newja.put(tagName); - if (ja != null) { - ja.put(newja); - } - } else { - newjo.put("tagName", tagName); - if (ja != null) { - ja.put(newjo); - } - } - token = null; - for (;;) { - if (token == null) { - token = x.nextToken(); - } - if (token == null) { - throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { - break; - } - -// attribute = value - - attribute = (String)token; - if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { - throw x.syntaxError("Reserved attribute."); - } - token = x.nextToken(); - if (token == XML.EQ) { - token = x.nextToken(); - if (!(token instanceof String)) { - throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String)token)); - token = null; - } else { - newjo.accumulate(attribute, ""); - } - } - if (arrayForm && newjo.length() > 0) { - newja.put(newjo); - } - -// Empty tag <.../> - - if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - -// Content, between <...> and - - } else { - if (token != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - closeTag = (String)parse(x, arrayForm, newja); - if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + - "' and '" + closeTag + "'"); - } - tagName = null; - if (!arrayForm && newja.length() > 0) { - newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - } - } - } - } else { - if (ja != null) { - ja.put(token instanceof String - ? XML.stringToValue((String)token) - : token); - } - } - } - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new XMLTokener(string)); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child content and tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(XMLTokener x) throws JSONException { - return (JSONArray)parse(x, true, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener of the XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject)parse(x, false, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - return toJSONObject(new XMLTokener(string)); - } - - - /** - * Reverse the JSONML transformation, making an XML text from a JSONArray. - * @param ja A JSONArray. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuffer sb = new StringBuffer(); - String tagName; - String value; - -// Emit = length) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - do { - object = ja.get(i); - i += 1; - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } - } - } while (i < length); - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } - - /** - * Reverse the JSONML transformation, making an XML text from a JSONObject. - * The JSONObject must contain a "tagName" property. If it has children, - * then it must have a "childNodes" property containing an array of objects. - * The other properties are attributes with string values. - * @param jo A JSONObject. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; - -//Emit '); - } else { - sb.append('>'); - length = ja.length(); - for (i = 0; i < length; i += 1) { - object = ja.get(i); - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } else { - sb.append(object.toString()); - } - } - } - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } -} diff --git a/wdl/org/json/JSONObject.java b/wdl/org/json/JSONObject.java deleted file mode 100755 index ffe5315..0000000 --- a/wdl/org/json/JSONObject.java +++ /dev/null @@ -1,1593 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; - -/** - * A JSONObject is an unordered collection of name/value pairs. Its external - * form is a string wrapped in curly braces with colons between the names and - * values, and commas between the values and names. The internal form is an - * object having get and opt methods for accessing the - * values by name, and put methods for adding or replacing values - * by name. The values can be any of these types: Boolean, - * JSONArray, JSONObject, Number, - * String, or the JSONObject.NULL object. A JSONObject - * constructor can be used to convert an external form JSON text into an - * internal form whose values can be retrieved with the get and - * opt methods, or to convert values into a JSON text using the - * put and toString methods. A get method - * returns a value if one can be found, and throws an exception if one cannot be - * found. An opt method returns a default value instead of throwing - * an exception, and so is useful for obtaining optional values. - *

- * The generic get() and opt() methods return an - * object, which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. The opt methods differ from the get methods in that they do - * not throw. Instead, they return a specified value, such as null. - *

- * The put methods add or replace values in an object. For example, - * - *

- * myString = new JSONObject().put("JSON", "Hello, World!").toString();
- * 
- * - * produces the string {"JSON": "Hello, World"}. - *

- * The texts produced by the toString methods strictly conform to - * the JSON syntax rules. The constructors are more forgiving in the texts they - * will accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing brace.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
  • - *
  • Keys can be followed by = or => as well as by - * :.
  • - *
  • Values can be followed by ; (semicolon) as - * well as by , (comma).
  • - *
- * - * @author JSON.org - * @version 2012-07-02 - */ -public class JSONObject { - - /** - * JSONObject.NULL is equivalent to the value that JavaScript calls null, - * whilst Java's null is equivalent to the value that JavaScript calls - * undefined. - */ - private static final class Null { - - /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. - * @return NULL. - */ - protected final Object clone() { - return this; - } - - /** - * A Null object is equal to the null value and to itself. - * @param object An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object - * or null. - */ - public boolean equals(Object object) { - return object == null || object == this; - } - - /** - * Get the "null" string value. - * @return The string "null". - */ - public String toString() { - return "null"; - } - } - - - /** - * The map where the JSONObject's properties are kept. - */ - private final Map map; - - - /** - * It is sometimes more convenient and less ambiguous to have a - * NULL object than to use Java's null value. - * JSONObject.NULL.equals(null) returns true. - * JSONObject.NULL.toString() returns "null". - */ - public static final Object NULL = new Null(); - - - /** - * Construct an empty JSONObject. - */ - public JSONObject() { - this.map = new HashMap(); - } - - - /** - * Construct a JSONObject from a subset of another JSONObject. - * An array of strings is used to identify the keys that should be copied. - * Missing keys are ignored. - * @param jo A JSONObject. - * @param names An array of strings. - * @throws JSONException - * @exception JSONException If a value is a non-finite number or if a name is duplicated. - */ - public JSONObject(JSONObject jo, String[] names) { - this(); - for (int i = 0; i < names.length; i += 1) { - try { - this.putOnce(names[i], jo.opt(names[i])); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a JSONTokener. - * @param x A JSONTokener object containing the source string. - * @throws JSONException If there is a syntax error in the source string - * or a duplicated key. - */ - public JSONObject(JSONTokener x) throws JSONException { - this(); - char c; - String key; - - if (x.nextClean() != '{') { - throw x.syntaxError("A JSONObject text must begin with '{'"); - } - for (;;) { - c = x.nextClean(); - switch (c) { - case 0: - throw x.syntaxError("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); - } - -// The key is followed by ':'. We will also tolerate '=' or '=>'. - - c = x.nextClean(); - if (c == '=') { - if (x.next() != '>') { - x.back(); - } - } else if (c != ':') { - throw x.syntaxError("Expected a ':' after a key"); - } - this.putOnce(key, x.nextValue()); - -// Pairs are separated by ','. We will also tolerate ';'. - - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { - return; - } - x.back(); - break; - case '}': - return; - default: - throw x.syntaxError("Expected a ',' or '}'"); - } - } - } - - - /** - * Construct a JSONObject from a Map. - * - * @param map A map object that can be used to initialize the contents of - * the JSONObject. - * @throws JSONException - */ - public JSONObject(Map map) { - this.map = new HashMap(); - if (map != null) { - Iterator i = map.entrySet().iterator(); - while (i.hasNext()) { - Map.Entry e = (Map.Entry)i.next(); - Object value = e.getValue(); - if (value != null) { - this.map.put(e.getKey(), wrap(value)); - } - } - } - } - - - /** - * Construct a JSONObject from an Object using bean getters. - * It reflects on all of the public methods of the object. - * For each of the methods with no parameters and a name starting - * with "get" or "is" followed by an uppercase letter, - * the method is invoked, and a key and the value returned from the getter method - * are put into the new JSONObject. - * - * The key is formed by removing the "get" or "is" prefix. - * If the second remaining character is not upper case, then the first - * character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is "Larry Fine", - * then the JSONObject will contain "name": "Larry Fine". - * - * @param bean An object that has getter methods that should be used - * to make a JSONObject. - */ - public JSONObject(Object bean) { - this(); - this.populateMap(bean); - } - - - /** - * Construct a JSONObject from an Object, using reflection to find the - * public members. The resulting JSONObject's keys will be the strings - * from the names array, and the values will be the field values associated - * with those keys in the object. If a key is not found or not visible, - * then it will not be copied into the new JSONObject. - * @param object An object that has fields that should be used to make a - * JSONObject. - * @param names An array of strings, the names of the fields to be obtained - * from the object. - */ - public JSONObject(Object object, String names[]) { - this(); - Class c = object.getClass(); - for (int i = 0; i < names.length; i += 1) { - String name = names[i]; - try { - this.putOpt(name, c.getField(name).get(object)); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a source JSON text string. - * This is the most commonly used JSONObject constructor. - * @param source A string beginning - * with { (left brace) and ending - * with } (right brace). - * @exception JSONException If there is a syntax error in the source - * string or a duplicated key. - */ - public JSONObject(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONObject from a ResourceBundle. - * @param baseName The ResourceBundle base name. - * @param locale The Locale to load the ResourceBundle for. - * @throws JSONException If any JSONExceptions are detected. - */ - public JSONObject(String baseName, Locale locale) throws JSONException { - this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, - Thread.currentThread().getContextClassLoader()); - -// Iterate through the keys in the bundle. - - Enumeration keys = bundle.getKeys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - if (key instanceof String) { - -// Go through the path, ensuring that there is a nested JSONObject for each -// segment except the last. Add the value using the last segment's name into -// the deepest nested JSONObject. - - String[] path = ((String)key).split("\\."); - int last = path.length - 1; - JSONObject target = this; - for (int i = 0; i < last; i += 1) { - String segment = path[i]; - JSONObject nextTarget = target.optJSONObject(segment); - if (nextTarget == null) { - nextTarget = new JSONObject(); - target.put(segment, nextTarget); - } - target = nextTarget; - } - target.put(path[last], bundle.getString((String)key)); - } - } - } - - - /** - * Accumulate values under a key. It is similar to the put method except - * that if there is already an object stored under the key then a - * JSONArray is stored under the key to hold all of the accumulated values. - * If there is already a JSONArray, then the new value is appended to it. - * In contrast, the put method replaces the previous value. - * - * If only one value is accumulated that is not a JSONArray, then the - * result will be the same as using put. But if multiple values are - * accumulated, then the result will be like append. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the value is an invalid number - * or if the key is null. - */ - public JSONObject accumulate( - String key, - Object value - ) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, value instanceof JSONArray - ? new JSONArray().put(value) - : value); - } else if (object instanceof JSONArray) { - ((JSONArray)object).put(value); - } else { - this.put(key, new JSONArray().put(object).put(value)); - } - return this; - } - - - /** - * Append values to the array under a key. If the key does not exist in the - * JSONObject, then the key is put in the JSONObject with its value being a - * JSONArray containing the value parameter. If the key was already - * associated with a JSONArray, then the value parameter is appended to it. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the key is null or if the current value - * associated with the key is not a JSONArray. - */ - public JSONObject append(String key, Object value) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, new JSONArray().put(value)); - } else if (object instanceof JSONArray) { - this.put(key, ((JSONArray)object).put(value)); - } else { - throw new JSONException("JSONObject[" + key + - "] is not a JSONArray."); - } - return this; - } - - - /** - * Produce a string from a double. The string "null" will be returned if - * the number is not finite. - * @param d A double. - * @return A String. - */ - public static String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { - return "null"; - } - -// Shave off trailing zeros and decimal point, if possible. - - String string = Double.toString(d); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get the value object associated with a key. - * - * @param key A key string. - * @return The object associated with the key. - * @throws JSONException if the key is not found. - */ - public Object get(String key) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - Object object = this.opt(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + - "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with a key. - * - * @param key A key string. - * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a Boolean."); - } - - - /** - * Get the double value associated with a key. - * @param key A key string. - * @return The numeric value. - * @throws JSONException if the key is not found or - * if the value is not a Number object and cannot be converted to a number. - */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a number."); - } - } - - - /** - * Get the int value associated with a key. - * - * @param key A key string. - * @return The integer value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to an integer. - */ - public int getInt(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not an int."); - } - } - - - /** - * Get the JSONArray value associated with a key. - * - * @param key A key string. - * @return A JSONArray which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONArray. - */ - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject value associated with a key. - * - * @param key A key string. - * @return A JSONObject which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONObject. - */ - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with a key. - * - * @param key A key string. - * @return The long value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to a long. - */ - public long getLong(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a long."); - } - } - - - /** - * Get an array of field names from a JSONObject. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(JSONObject jo) { - int length = jo.length(); - if (length == 0) { - return null; - } - Iterator iterator = jo.keys(); - String[] names = new String[length]; - int i = 0; - while (iterator.hasNext()) { - names[i] = (String)iterator.next(); - i += 1; - } - return names; - } - - - /** - * Get an array of field names from an Object. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(Object object) { - if (object == null) { - return null; - } - Class klass = object.getClass(); - Field[] fields = klass.getFields(); - int length = fields.length; - if (length == 0) { - return null; - } - String[] names = new String[length]; - for (int i = 0; i < length; i += 1) { - names[i] = fields[i].getName(); - } - return names; - } - - - /** - * Get the string associated with a key. - * - * @param key A key string. - * @return A string which is the value. - * @throws JSONException if there is no string value for the key. - */ - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] not a string."); - } - - - /** - * Determine if the JSONObject contains a specific key. - * @param key A key string. - * @return true if the key exists in the JSONObject. - */ - public boolean has(String key) { - return this.map.containsKey(key); - } - - - /** - * Increment a property of a JSONObject. If there is no such property, - * create one with a value of 1. If there is such a property, and if - * it is an Integer, Long, Double, or Float, then add one to it. - * @param key A key string. - * @return this. - * @throws JSONException If there is already a property with this name - * that is not an Integer, Long, Double, or Float. - */ - public JSONObject increment(String key) throws JSONException { - Object value = this.opt(key); - if (value == null) { - this.put(key, 1); - } else if (value instanceof Integer) { - this.put(key, ((Integer)value).intValue() + 1); - } else if (value instanceof Long) { - this.put(key, ((Long)value).longValue() + 1); - } else if (value instanceof Double) { - this.put(key, ((Double)value).doubleValue() + 1); - } else if (value instanceof Float) { - this.put(key, ((Float)value).floatValue() + 1); - } else { - throw new JSONException("Unable to increment [" + quote(key) + "]."); - } - return this; - } - - - /** - * Determine if the value associated with the key is null or if there is - * no value. - * @param key A key string. - * @return true if there is no value associated with the key or if - * the value is the JSONObject.NULL object. - */ - public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); - } - - - /** - * Get an enumeration of the keys of the JSONObject. - * - * @return An iterator of the keys. - */ - public Iterator keys() { - return this.map.keySet().iterator(); - } - - - /** - * Get the number of keys stored in the JSONObject. - * - * @return The number of keys in the JSONObject. - */ - public int length() { - return this.map.size(); - } - - - /** - * Produce a JSONArray containing the names of the elements of this - * JSONObject. - * @return A JSONArray containing the key strings, or null if the JSONObject - * is empty. - */ - public JSONArray names() { - JSONArray ja = new JSONArray(); - Iterator keys = this.keys(); - while (keys.hasNext()) { - ja.put(keys.next()); - } - return ja.length() == 0 ? null : ja; - } - - /** - * Produce a string from a Number. - * @param number A Number - * @return A String. - * @throws JSONException If n is a non-finite number. - */ - public static String numberToString(Number number) - throws JSONException { - if (number == null) { - throw new JSONException("Null pointer"); - } - testValidity(number); - -// Shave off trailing zeros and decimal point, if possible. - - String string = number.toString(); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get an optional value associated with a key. - * @param key A key string. - * @return An object which is the value, or null if there is no value. - */ - public Object opt(String key) { - return key == null ? null : this.map.get(key); - } - - - /** - * Get an optional boolean associated with a key. - * It returns false if there is no such key, or if the value is not - * Boolean.TRUE or the String "true". - * - * @param key A key string. - * @return The truth. - */ - public boolean optBoolean(String key) { - return this.optBoolean(key, false); - } - - - /** - * Get an optional boolean associated with a key. - * It returns the defaultValue if there is no such key, or if it is not - * a Boolean or the String "true" or "false" (case insensitive). - * - * @param key A key string. - * @param defaultValue The default. - * @return The truth. - */ - public boolean optBoolean(String key, boolean defaultValue) { - try { - return this.getBoolean(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional double associated with a key, - * or NaN if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A string which is the key. - * @return An object which is the value. - */ - public double optDouble(String key) { - return this.optDouble(key, Double.NaN); - } - - - /** - * Get an optional double associated with a key, or the - * defaultValue if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public double optDouble(String key, double defaultValue) { - try { - return this.getDouble(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional int value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public int optInt(String key) { - return this.optInt(key, 0); - } - - - /** - * Get an optional int value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public int optInt(String key, int defaultValue) { - try { - return this.getInt(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional JSONArray associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONArray. - * - * @param key A key string. - * @return A JSONArray which is the value. - */ - public JSONArray optJSONArray(String key) { - Object o = this.opt(key); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get an optional JSONObject associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONObject. - * - * @param key A key string. - * @return A JSONObject which is the value. - */ - public JSONObject optJSONObject(String key) { - Object object = this.opt(key); - return object instanceof JSONObject ? (JSONObject)object : null; - } - - - /** - * Get an optional long value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public long optLong(String key) { - return this.optLong(key, 0); - } - - - /** - * Get an optional long value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public long optLong(String key, long defaultValue) { - try { - return this.getLong(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional string associated with a key. - * It returns an empty string if there is no such key. If the value is not - * a string and is not null, then it is converted to a string. - * - * @param key A key string. - * @return A string which is the value. - */ - public String optString(String key) { - return this.optString(key, ""); - } - - - /** - * Get an optional string associated with a key. - * It returns the defaultValue if there is no such key. - * - * @param key A key string. - * @param defaultValue The default. - * @return A string which is the value. - */ - public String optString(String key, String defaultValue) { - Object object = this.opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); - } - - - private void populateMap(Object bean) { - Class klass = bean.getClass(); - -// If klass is a System class then set includeSuperClass to false. - - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass - ? klass.getMethods() - : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || - "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && - Character.isUpperCase(key.charAt(0)) && - method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + - key.substring(1); - } - - Object result = method.invoke(bean, (Object[])null); - if (result != null) { - this.map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - } - - - /** - * Put a key/boolean pair in the JSONObject. - * - * @param key A key string. - * @param value A boolean which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, boolean value) throws JSONException { - this.put(key, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONArray which is produced from a Collection. - * @param key A key string. - * @param value A Collection value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Collection value) throws JSONException { - this.put(key, new JSONArray(value)); - return this; - } - - - /** - * Put a key/double pair in the JSONObject. - * - * @param key A key string. - * @param value A double which is the value. - * @return this. - * @throws JSONException If the key is null or if the number is invalid. - */ - public JSONObject put(String key, double value) throws JSONException { - this.put(key, new Double(value)); - return this; - } - - - /** - * Put a key/int pair in the JSONObject. - * - * @param key A key string. - * @param value An int which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, int value) throws JSONException { - this.put(key, new Integer(value)); - return this; - } - - - /** - * Put a key/long pair in the JSONObject. - * - * @param key A key string. - * @param value A long which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, long value) throws JSONException { - this.put(key, new Long(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONObject which is produced from a Map. - * @param key A key string. - * @param value A Map value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Map value) throws JSONException { - this.put(key, new JSONObject(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject. If the value is null, - * then the key will be removed from the JSONObject if it is present. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is non-finite number - * or if the key is null. - */ - public JSONObject put(String key, Object value) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - if (value != null) { - testValidity(value); - this.map.put(key, value); - } else { - this.remove(key); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the key and the - * value are both non-null, and only if there is not already a member - * with that name. - * @param key - * @param value - * @return his. - * @throws JSONException if the key is a duplicate - */ - public JSONObject putOnce(String key, Object value) throws JSONException { - if (key != null && value != null) { - if (this.opt(key) != null) { - throw new JSONException("Duplicate key \"" + key + "\""); - } - this.put(key, value); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the - * key and the value are both non-null. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is a non-finite number. - */ - public JSONObject putOpt(String key, Object value) throws JSONException { - if (key != null && value != null) { - this.put(key, value); - } - return this; - } - - - /** - * Produce a string in double quotes with backslash sequences in all the - * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - hhhh = "000" + Integer.toHexString(c); - w.write("\\u" + hhhh.substring(hhhh.length() - 4)); - } else { - w.write(c); - } - } - } - w.write('"'); - return w; - } - - /** - * Remove a name and its value, if present. - * @param key The name to be removed. - * @return The value that was associated with the name, - * or null if there was no value. - */ - public Object remove(String key) { - return this.map.remove(key); - } - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - Double d; - if (string.equals("")) { - return string; - } - if (string.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { - return JSONObject.NULL; - } - - /* - * If it might be a number, try converting it. - * If a number cannot be produced, then the value will just - * be a string. Note that the plus and implied string - * conventions are non-standard. A JSON parser may accept - * non-JSON forms as long as it accepts all correct JSON forms. - */ - - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { - try { - if (string.indexOf('.') > -1 || - string.indexOf('e') > -1 || string.indexOf('E') > -1) { - d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { - return d; - } - } else { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } catch (Exception ignore) { - } - } - return string; - } - - - /** - * Throw an exception if the object is a NaN or infinite number. - * @param o The object to test. - * @throws JSONException If o is a non-finite number. - */ - public static void testValidity(Object o) throws JSONException { - if (o != null) { - if (o instanceof Double) { - if (((Double)o).isInfinite() || ((Double)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float)o).isInfinite() || ((Float)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } - } - } - - - /** - * Produce a JSONArray containing the values of the members of this - * JSONObject. - * @param names A JSONArray containing a list of key strings. This - * determines the sequence of the values in the result. - * @return A JSONArray of values. - * @throws JSONException If any of the values are non-finite numbers. - */ - public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (int i = 0; i < names.length(); i += 1) { - ja.put(this.opt(names.getString(i))); - } - return ja; - } - - /** - * Make a JSON text of this JSONObject. For compactness, no whitespace - * is added. If this would not result in a syntactically correct JSON text, - * then null will be returned instead. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - */ - public String toString() { - try { - return this.toString(0); - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

- * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the object contains an invalid number. - */ - public String toString(int indentFactor) throws JSONException { - StringWriter w = new StringWriter(); - synchronized (w.getBuffer()) { - return this.write(w, indentFactor, 0).toString(); - } - } - - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce - * the JSON text. The method is required to produce a strictly - * conforming text. If the object does not contain a toJSONString - * method (which is the most common case), then a text will be - * produced by other means. If the value is an array or Collection, - * then a JSONArray will be made from it and its toJSONString method - * will be called. If the value is a MAP, then a JSONObject will be made - * from it and its toJSONString method will be called. Otherwise, the - * value's toString method will be called, and the result will be quoted. - * - *

- * Warning: This method assumes that the data structure is acyclical. - * @param value The value to be serialized. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the value is or contains an invalid number. - */ - public static String valueToString(Object value) throws JSONException { - if (value == null || value.equals(null)) { - return "null"; - } - if (value instanceof JSONString) { - Object object; - try { - object = ((JSONString)value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - if (object instanceof String) { - return (String)object; - } - throw new JSONException("Bad value from toJSONString: " + object); - } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean || value instanceof JSONObject || - value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - return new JSONObject((Map)value).toString(); - } - if (value instanceof Collection) { - return new JSONArray((Collection)value).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); - } - return quote(value.toString()); - } - - /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If - * it is a map, wrap it in a JSONObject. If it is a standard property - * (Double, String, et al) then it is already wrapped. Otherwise, if it - * comes from one of the java packages, turn it into a string. And if - * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, - * then null is returned. - * - * @param object The object to wrap - * @return The wrapped value - */ - public static Object wrap(Object object) { - try { - if (object == null) { - return NULL; - } - if (object instanceof JSONObject || object instanceof JSONArray || - NULL.equals(object) || object instanceof JSONString || - object instanceof Byte || object instanceof Character || - object instanceof Short || object instanceof Integer || - object instanceof Long || object instanceof Boolean || - object instanceof Float || object instanceof Double || - object instanceof String || object instanceof Enum) { - return object; - } - - if (object instanceof Collection) { - return new JSONArray((Collection)object); - } - if (object.getClass().isArray()) { - return new JSONArray(object); - } - if (object instanceof Map) { - return new JSONObject((Map)object); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null - ? objectPackage.getName() - : ""; - if ( - objectPackageName.startsWith("java.") || - objectPackageName.startsWith("javax.") || - object.getClass().getClassLoader() == null - ) { - return object.toString(); - } - return new JSONObject(object); - } catch(Exception exception) { - return null; - } - } - - - /** - * Write the contents of the JSONObject as JSON text to a writer. - * For compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - - static final Writer writeValue(Writer writer, Object value, - int indentFactor, int indent) throws JSONException, IOException { - if (value == null || value.equals(null)) { - writer.write("null"); - } else if (value instanceof JSONObject) { - ((JSONObject) value).write(writer, indentFactor, indent); - } else if (value instanceof JSONArray) { - ((JSONArray) value).write(writer, indentFactor, indent); - } else if (value instanceof Map) { - new JSONObject((Map) value).write(writer, indentFactor, indent); - } else if (value instanceof Collection) { - new JSONArray((Collection) value).write(writer, indentFactor, - indent); - } else if (value.getClass().isArray()) { - new JSONArray(value).write(writer, indentFactor, indent); - } else if (value instanceof Number) { - writer.write(numberToString((Number) value)); - } else if (value instanceof Boolean) { - writer.write(value.toString()); - } else if (value instanceof JSONString) { - Object o; - try { - o = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - writer.write(o != null ? o.toString() : quote(value.toString())); - } else { - quote(value.toString(), writer); - } - return writer; - } - - static final void indent(Writer writer, int indent) throws IOException { - for (int i = 0; i < indent; i += 1) { - writer.write(' '); - } - } - - /** - * Write the contents of the JSONObject as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - final int length = this.length(); - Iterator keys = this.keys(); - writer.write('{'); - - if (length == 1) { - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - while (keys.hasNext()) { - Object key = keys.next(); - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, newindent); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, - newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, indent); - } - writer.write('}'); - return writer; - } catch (IOException exception) { - throw new JSONException(exception); - } - } -} diff --git a/wdl/org/json/JSONString.java b/wdl/org/json/JSONString.java deleted file mode 100755 index 41726b1..0000000 --- a/wdl/org/json/JSONString.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.json; -/** - * The JSONString interface allows a toJSONString() - * method so that a class can change the behavior of - * JSONObject.toString(), JSONArray.toString(), - * and JSONWriter.value(Object). The - * toJSONString method will be used instead of the default behavior - * of using the Object's toString() method and quoting the result. - */ -public interface JSONString { - /** - * The toJSONString method allows a class to produce its own JSON - * serialization. - * - * @return A strictly syntactically correct JSON text. - */ - public String toJSONString(); -} diff --git a/wdl/org/json/JSONStringer.java b/wdl/org/json/JSONStringer.java deleted file mode 100755 index 25c2e5d..0000000 --- a/wdl/org/json/JSONStringer.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.json; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.StringWriter; - -/** - * JSONStringer provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONStringer can produce one JSON text. - *

- * A JSONStringer instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting cascade style. For example,

- * myString = new JSONStringer()
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject()
- *     .toString();
which produces the string
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONStringer adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2008-09-18 - */ -public class JSONStringer extends JSONWriter { - /** - * Make a fresh JSONStringer. It can be used to build one JSON text. - */ - public JSONStringer() { - super(new StringWriter()); - } - - /** - * Return the JSON text. This method is used to obtain the product of the - * JSONStringer instance. It will return null if there was a - * problem in the construction of the JSON text (such as the calls to - * array were not properly balanced with calls to - * endArray). - * @return The JSON text. - */ - public String toString() { - return this.mode == 'd' ? this.writer.toString() : null; - } -} diff --git a/wdl/org/json/JSONTokener.java b/wdl/org/json/JSONTokener.java deleted file mode 100644 index 13c84f1..0000000 --- a/wdl/org/json/JSONTokener.java +++ /dev/null @@ -1,446 +0,0 @@ -package org.json; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. - * @author JSON.org - * @version 2012-02-16 - */ -public class JSONTokener { - - private long character; - private boolean eof; - private long index; - private long line; - private char previous; - private Reader reader; - private boolean usePrevious; - - - /** - * Construct a JSONTokener from a Reader. - * - * @param reader A reader. - */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader - : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; - } - - - /** - * Construct a JSONTokener from an InputStream. - */ - public JSONTokener(InputStream inputStream) throws JSONException { - this(new InputStreamReader(inputStream)); - } - - - /** - * Construct a JSONTokener from a string. - * - * @param s A source string. - */ - public JSONTokener(String s) { - this(new StringReader(s)); - } - - - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. - */ - public void back() throws JSONException { - if (this.usePrevious || this.index <= 0) { - throw new JSONException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; - } - - - /** - * Get the hex value of a character (base16). - * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. - */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { - return c - ('a' - 10); - } - return -1; - } - - public boolean end() { - return this.eof && !this.usePrevious; - } - - - /** - * Determine if the source string still contains characters that next() - * can consume. - * @return true if not yet at the end of the source. - */ - public boolean more() throws JSONException { - this.next(); - if (this.end()) { - return false; - } - this.back(); - return true; - } - - - /** - * Get the next character in the source string. - * - * @return The next character, or 0 if past the end of the source string. - */ - public char next() throws JSONException { - int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { - try { - c = this.reader.read(); - } catch (IOException exception) { - throw new JSONException(exception); - } - - if (c <= 0) { // End of stream - this.eof = true; - c = 0; - } - } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; - } - this.previous = (char) c; - return this.previous; - } - - - /** - * Consume the next character, and check that it matches a specified - * character. - * @param c The character to match. - * @return The character. - * @throws JSONException if the character does not match. - */ - public char next(char c) throws JSONException { - char n = this.next(); - if (n != c) { - throw this.syntaxError("Expected '" + c + "' and instead saw '" + - n + "'"); - } - return n; - } - - - /** - * Get the next n characters. - * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. - */ - public String next(int n) throws JSONException { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw this.syntaxError("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - - - /** - * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. - */ - public char nextClean() throws JSONException { - for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { - return c; - } - } - } - - - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string. - */ - public String nextString(char quote) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw this.syntaxError("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); - } - } - } - - - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. - */ - public String nextTo(char delimiter) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = this.next(); - if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the text up but not including one of the specified delimiter - * characters or the end of line, whichever comes first. - * @param delimiters A set of delimiter characters. - * @return A string, trimmed. - */ - public String nextTo(String delimiters) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the next value. The value can be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. - * - * @return An object. - */ - public Object nextValue() throws JSONException { - char c = this.nextClean(); - String string; - - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - this.back(); - return new JSONObject(this); - case '[': - this.back(); - return new JSONArray(this); - } - - /* - * Handle unquoted text. This could be the values true, false, or - * null, or it can be a number. An implementation (such as this one) - * is allowed to also accept non-standard forms. - * - * Accumulate characters until we reach the end of the text or a - * formatting character. - */ - - StringBuffer sb = new StringBuffer(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - string = sb.toString().trim(); - if ("".equals(string)) { - throw this.syntaxError("Missing value"); - } - return JSONObject.stringToValue(string); - } - - - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. - * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. - */ - public char skipTo(char to) throws JSONException { - char c; - try { - long startIndex = this.index; - long startCharacter = this.character; - long startLine = this.line; - this.reader.mark(1000000); - do { - c = this.next(); - if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; - return c; - } - } while (c != to); - } catch (IOException exc) { - throw new JSONException(exc); - } - - this.back(); - return c; - } - - - /** - * Make a JSONException to signal a syntax error. - * - * @param message The error message. - * @return A JSONException object, suitable for throwing - */ - public JSONException syntaxError(String message) { - return new JSONException(message + this.toString()); - } - - - /** - * Make a printable string of this JSONTokener. - * - * @return " at {index} [character {character} line {line}]" - */ - public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; - } -} diff --git a/wdl/org/json/JSONWriter.java b/wdl/org/json/JSONWriter.java deleted file mode 100755 index 855b2bd..0000000 --- a/wdl/org/json/JSONWriter.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.json; - -import java.io.IOException; -import java.io.Writer; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * JSONWriter provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONWriter can produce one JSON text. - *

- * A JSONWriter instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting a cascade style. For example,

- * new JSONWriter(myWriter)
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject();
which writes
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONWriter { - private static final int maxdepth = 200; - - /** - * The comma flag determines if a comma should be output before the next - * value. - */ - private boolean comma; - - /** - * The current mode. Values: - * 'a' (array), - * 'd' (done), - * 'i' (initial), - * 'k' (key), - * 'o' (object). - */ - protected char mode; - - /** - * The object/array stack. - */ - private final JSONObject stack[]; - - /** - * The stack top index. A value of 0 indicates that the stack is empty. - */ - private int top; - - /** - * The writer that will receive the output. - */ - protected Writer writer; - - /** - * Make a fresh JSONWriter. It can be used to build one JSON text. - */ - public JSONWriter(Writer w) { - this.comma = false; - this.mode = 'i'; - this.stack = new JSONObject[maxdepth]; - this.top = 0; - this.writer = w; - } - - /** - * Append a value. - * @param string A string value. - * @return this - * @throws JSONException If the value is out of sequence. - */ - private JSONWriter append(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null pointer"); - } - if (this.mode == 'o' || this.mode == 'a') { - try { - if (this.comma && this.mode == 'a') { - this.writer.write(','); - } - this.writer.write(string); - } catch (IOException e) { - throw new JSONException(e); - } - if (this.mode == 'o') { - this.mode = 'k'; - } - this.comma = true; - return this; - } - throw new JSONException("Value out of sequence."); - } - - /** - * Begin appending a new array. All values until the balancing - * endArray will be appended to this array. The - * endArray method must be called to mark the array's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter array() throws JSONException { - if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { - this.push(null); - this.append("["); - this.comma = false; - return this; - } - throw new JSONException("Misplaced array."); - } - - /** - * End something. - * @param mode Mode - * @param c Closing character - * @return this - * @throws JSONException If unbalanced. - */ - private JSONWriter end(char mode, char c) throws JSONException { - if (this.mode != mode) { - throw new JSONException(mode == 'a' - ? "Misplaced endArray." - : "Misplaced endObject."); - } - this.pop(mode); - try { - this.writer.write(c); - } catch (IOException e) { - throw new JSONException(e); - } - this.comma = true; - return this; - } - - /** - * End an array. This method most be called to balance calls to - * array. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endArray() throws JSONException { - return this.end('a', ']'); - } - - /** - * End an object. This method most be called to balance calls to - * object. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endObject() throws JSONException { - return this.end('k', '}'); - } - - /** - * Append a key. The key will be associated with the next value. In an - * object, every value must be preceded by a key. - * @param string A key string. - * @return this - * @throws JSONException If the key is out of place. For example, keys - * do not belong in arrays or if the key is null. - */ - public JSONWriter key(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null key."); - } - if (this.mode == 'k') { - try { - this.stack[this.top - 1].putOnce(string, Boolean.TRUE); - if (this.comma) { - this.writer.write(','); - } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); - this.comma = false; - this.mode = 'o'; - return this; - } catch (IOException e) { - throw new JSONException(e); - } - } - throw new JSONException("Misplaced key."); - } - - - /** - * Begin appending a new object. All keys and values until the balancing - * endObject will be appended to this object. The - * endObject method must be called to mark the object's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter object() throws JSONException { - if (this.mode == 'i') { - this.mode = 'o'; - } - if (this.mode == 'o' || this.mode == 'a') { - this.append("{"); - this.push(new JSONObject()); - this.comma = false; - return this; - } - throw new JSONException("Misplaced object."); - - } - - - /** - * Pop an array or object scope. - * @param c The scope to close. - * @throws JSONException If nesting is wrong. - */ - private void pop(char c) throws JSONException { - if (this.top <= 0) { - throw new JSONException("Nesting error."); - } - char m = this.stack[this.top - 1] == null ? 'a' : 'k'; - if (m != c) { - throw new JSONException("Nesting error."); - } - this.top -= 1; - this.mode = this.top == 0 - ? 'd' - : this.stack[this.top - 1] == null - ? 'a' - : 'k'; - } - - /** - * Push an array or object scope. - * @param c The scope to open. - * @throws JSONException If nesting is too deep. - */ - private void push(JSONObject jo) throws JSONException { - if (this.top >= maxdepth) { - throw new JSONException("Nesting too deep."); - } - this.stack[this.top] = jo; - this.mode = jo == null ? 'a' : 'k'; - this.top += 1; - } - - - /** - * Append either the value true or the value - * false. - * @param b A boolean. - * @return this - * @throws JSONException - */ - public JSONWriter value(boolean b) throws JSONException { - return this.append(b ? "true" : "false"); - } - - /** - * Append a double value. - * @param d A double. - * @return this - * @throws JSONException If the number is not finite. - */ - public JSONWriter value(double d) throws JSONException { - return this.value(new Double(d)); - } - - /** - * Append a long value. - * @param l A long. - * @return this - * @throws JSONException - */ - public JSONWriter value(long l) throws JSONException { - return this.append(Long.toString(l)); - } - - - /** - * Append an object value. - * @param object The object to append. It can be null, or a Boolean, Number, - * String, JSONObject, or JSONArray, or an object that implements JSONString. - * @return this - * @throws JSONException If the value is out of sequence. - */ - public JSONWriter value(Object object) throws JSONException { - return this.append(JSONObject.valueToString(object)); - } -} diff --git a/wdl/org/json/XML.java b/wdl/org/json/XML.java deleted file mode 100755 index 82455b3..0000000 --- a/wdl/org/json/XML.java +++ /dev/null @@ -1,508 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONObject, - * and to covert a JSONObject into an XML text. - * @author JSON.org - * @version 2011-02-11 - */ -public class XML { - - /** The Character '&'. */ - public static final Character AMP = new Character('&'); - - /** The Character '''. */ - public static final Character APOS = new Character('\''); - - /** The Character '!'. */ - public static final Character BANG = new Character('!'); - - /** The Character '='. */ - public static final Character EQ = new Character('='); - - /** The Character '>'. */ - public static final Character GT = new Character('>'); - - /** The Character '<'. */ - public static final Character LT = new Character('<'); - - /** The Character '?'. */ - public static final Character QUEST = new Character('?'); - - /** The Character '"'. */ - public static final Character QUOT = new Character('"'); - - /** The Character '/'. */ - public static final Character SLASH = new Character('/'); - - /** - * Replace special characters with XML escapes: - *

-     * & (ampersand) is replaced by &amp;
-     * < (less than) is replaced by &lt;
-     * > (greater than) is replaced by &gt;
-     * " (double quote) is replaced by &quot;
-     * 
- * @param string The string to be escaped. - * @return The escaped string. - */ - public static String escape(String string) { - StringBuffer sb = new StringBuffer(); - for (int i = 0, length = string.length(); i < length; i++) { - char c = string.charAt(i); - switch (c) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - default: - sb.append(c); - } - } - return sb.toString(); - } - - /** - * Throw an exception if the string contains whitespace. - * Whitespace is not allowed in tagNames and attributes. - * @param string - * @throws JSONException - */ - public static void noSpace(String string) throws JSONException { - int i, length = string.length(); - if (length == 0) { - throw new JSONException("Empty string."); - } - for (i = 0; i < length; i += 1) { - if (Character.isWhitespace(string.charAt(i))) { - throw new JSONException("'" + string + - "' contains a space character."); - } - } - } - - /** - * Scan the content following the named tag, attaching it to the context. - * @param x The XMLTokener containing the source string. - * @param context The JSONObject that will include the new material. - * @param name The tag name. - * @return true if the close tag is processed. - * @throws JSONException - */ - private static boolean parse(XMLTokener x, JSONObject context, - String name) throws JSONException { - char c; - int i; - JSONObject jsonobject = null; - String string; - String tagName; - Object token; - -// Test for and skip past these forms: -// -// -// -// -// Report errors for these forms: -// <> -// <= -// << - - token = x.nextToken(); - -// "); - return false; - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if ("CDATA".equals(token)) { - if (x.next() == '[') { - string = x.nextCDATA(); - if (string.length() > 0) { - context.accumulate("content", string); - } - return false; - } - } - throw x.syntaxError("Expected 'CDATA['"); - } - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - return false; - } else if (token == QUEST) { - -// "); - return false; - } else if (token == SLASH) { - -// Close tag - - } else if (token == SLASH) { - if (x.nextToken() != GT) { - throw x.syntaxError("Misshaped tag"); - } - if (jsonobject.length() > 0) { - context.accumulate(tagName, jsonobject); - } else { - context.accumulate(tagName, ""); - } - return false; - -// Content, between <...> and - - } else if (token == GT) { - for (;;) { - token = x.nextContent(); - if (token == null) { - if (tagName != null) { - throw x.syntaxError("Unclosed tag " + tagName); - } - return false; - } else if (token instanceof String) { - string = (String)token; - if (string.length() > 0) { - jsonobject.accumulate("content", - XML.stringToValue(string)); - } - -// Nested element - - } else if (token == LT) { - if (parse(x, jsonobject, tagName)) { - if (jsonobject.length() == 0) { - context.accumulate(tagName, ""); - } else if (jsonobject.length() == 1 && - jsonobject.opt("content") != null) { - context.accumulate(tagName, - jsonobject.opt("content")); - } else { - context.accumulate(tagName, jsonobject); - } - return false; - } - } - } - } else { - throw x.syntaxError("Misshaped tag"); - } - } - } - } - - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. This is much less ambitious than - * JSONObject.stringToValue, especially because it does not attempt to - * convert plus forms, octal forms, hex forms, or E forms lacking decimal - * points. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - if ("".equals(string)) { - return string; - } - if ("true".equalsIgnoreCase(string)) { - return Boolean.TRUE; - } - if ("false".equalsIgnoreCase(string)) { - return Boolean.FALSE; - } - if ("null".equalsIgnoreCase(string)) { - return JSONObject.NULL; - } - if ("0".equals(string)) { - return new Integer(0); - } - -// If it might be a number, try converting it. If that doesn't work, -// return the string. - - try { - char initial = string.charAt(0); - boolean negative = false; - if (initial == '-') { - initial = string.charAt(1); - negative = true; - } - if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') { - return string; - } - if ((initial >= '0' && initial <= '9')) { - if (string.indexOf('.') >= 0) { - return Double.valueOf(string); - } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } - } catch (Exception ignore) { - } - return string; - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject. Some information may be lost in this transformation - * because JSON is a data format and XML is a document format. XML uses - * elements, attributes, and content text, while JSON uses unordered - * collections of name/value pairs and arrays of values. JSON does not - * does not like to distinguish between elements and attributes. - * Sequences of similar elements are represented as JSONArrays. Content - * text may be placed in a "content" member. Comments, prologs, DTDs, and - * <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - XMLTokener x = new XMLTokener(string); - while (x.more() && x.skipPast("<")) { - parse(x, jo, null); - } - return jo; - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object) throws JSONException { - return toString(object, null); - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @param tagName The optional name of the enclosing tag. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object, String tagName) - throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - JSONObject jo; - String key; - Iterator keys; - int length; - String string; - Object value; - if (object instanceof JSONObject) { - -// Emit - - if (tagName != null) { - sb.append('<'); - sb.append(tagName); - sb.append('>'); - } - -// Loop thru the keys. - - jo = (JSONObject)object; - keys = jo.keys(); - while (keys.hasNext()) { - key = keys.next().toString(); - value = jo.opt(key); - if (value == null) { - value = ""; - } - if (value instanceof String) { - string = (String)value; - } else { - string = null; - } - -// Emit content in body - - if ("content".equals(key)) { - if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - if (i > 0) { - sb.append('\n'); - } - sb.append(escape(ja.get(i).toString())); - } - } else { - sb.append(escape(value.toString())); - } - -// Emit an array of similar keys - - } else if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - value = ja.get(i); - if (value instanceof JSONArray) { - sb.append('<'); - sb.append(key); - sb.append('>'); - sb.append(toString(value)); - sb.append("'); - } else { - sb.append(toString(value, key)); - } - } - } else if ("".equals(value)) { - sb.append('<'); - sb.append(key); - sb.append("/>"); - -// Emit a new tag - - } else { - sb.append(toString(value, key)); - } - } - if (tagName != null) { - -// Emit the close tag - - sb.append("'); - } - return sb.toString(); - -// XML does not have good support for arrays. If an array appears in a place -// where XML is lacking, synthesize an element. - - } else { - if (object.getClass().isArray()) { - object = new JSONArray(object); - } - if (object instanceof JSONArray) { - ja = (JSONArray)object; - length = ja.length(); - for (i = 0; i < length; i += 1) { - sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); - } - return sb.toString(); - } else { - string = (object == null) ? "null" : escape(object.toString()); - return (tagName == null) ? "\"" + string + "\"" : - (string.length() == 0) ? "<" + tagName + "/>" : - "<" + tagName + ">" + string + ""; - } - } - } -} \ No newline at end of file diff --git a/wdl/org/json/XMLTokener.java b/wdl/org/json/XMLTokener.java deleted file mode 100755 index 07574b0..0000000 --- a/wdl/org/json/XMLTokener.java +++ /dev/null @@ -1,365 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The XMLTokener extends the JSONTokener to provide additional methods - * for the parsing of XML texts. - * @author JSON.org - * @version 2010-12-24 - */ -public class XMLTokener extends JSONTokener { - - - /** The table of entity values. It initially contains Character values for - * amp, apos, gt, lt, quot. - */ - public static final java.util.HashMap entity; - - static { - entity = new java.util.HashMap(8); - entity.put("amp", XML.AMP); - entity.put("apos", XML.APOS); - entity.put("gt", XML.GT); - entity.put("lt", XML.LT); - entity.put("quot", XML.QUOT); - } - - /** - * Construct an XMLTokener from a string. - * @param s A source string. - */ - public XMLTokener(String s) { - super(s); - } - - /** - * Get the text in the CDATA block. - * @return The string up to the ]]>. - * @throws JSONException If the ]]> is not found. - */ - public String nextCDATA() throws JSONException { - char c; - int i; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = next(); - if (end()) { - throw syntaxError("Unclosed CDATA"); - } - sb.append(c); - i = sb.length() - 3; - if (i >= 0 && sb.charAt(i) == ']' && - sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { - sb.setLength(i); - return sb.toString(); - } - } - } - - - /** - * Get the next XML outer token, trimming whitespace. There are two kinds - * of tokens: the '<' character which begins a markup tag, and the content - * text between markup tags. - * - * @return A string, or a '<' Character, or null if there is no more - * source text. - * @throws JSONException - */ - public Object nextContent() throws JSONException { - char c; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == 0) { - return null; - } - if (c == '<') { - return XML.LT; - } - sb = new StringBuffer(); - for (;;) { - if (c == '<' || c == 0) { - back(); - return sb.toString().trim(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - c = next(); - } - } - - - /** - * Return the next entity. These entities are translated to Characters: - * & ' > < ". - * @param ampersand An ampersand character. - * @return A Character or an entity String if the entity is not recognized. - * @throws JSONException If missing ';' in XML entity. - */ - public Object nextEntity(char ampersand) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = next(); - if (Character.isLetterOrDigit(c) || c == '#') { - sb.append(Character.toLowerCase(c)); - } else if (c == ';') { - break; - } else { - throw syntaxError("Missing ';' in XML entity: &" + sb); - } - } - String string = sb.toString(); - Object object = entity.get(string); - return object != null ? object : ampersand + string + ";"; - } - - - /** - * Returns the next XML meta token. This is used for skipping over - * and structures. - * @return Syntax characters (< > / = ! ?) are returned as - * Character, and strings and names are returned as Boolean. We don't care - * what the values actually are. - * @throws JSONException If a string is not properly closed or if the XML - * is badly structured. - */ - public Object nextMeta() throws JSONException { - char c; - char q; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped meta tag"); - case '<': - return XML.LT; - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - case '"': - case '\'': - q = c; - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return Boolean.TRUE; - } - } - default: - for (;;) { - c = next(); - if (Character.isWhitespace(c)) { - return Boolean.TRUE; - } - switch (c) { - case 0: - case '<': - case '>': - case '/': - case '=': - case '!': - case '?': - case '"': - case '\'': - back(); - return Boolean.TRUE; - } - } - } - } - - - /** - * Get the next XML Token. These tokens are found inside of angle - * brackets. It may be one of these characters: / > = ! ? or it - * may be a string wrapped in single quotes or double quotes, or it may be a - * name. - * @return a String or a Character. - * @throws JSONException If the XML is not well formed. - */ - public Object nextToken() throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped element"); - case '<': - throw syntaxError("Misplaced '<'"); - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - -// Quoted string - - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return sb.toString(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - } - default: - -// Name - - sb = new StringBuffer(); - for (;;) { - sb.append(c); - c = next(); - if (Character.isWhitespace(c)) { - return sb.toString(); - } - switch (c) { - case 0: - return sb.toString(); - case '>': - case '/': - case '=': - case '!': - case '?': - case '[': - case ']': - back(); - return sb.toString(); - case '<': - case '"': - case '\'': - throw syntaxError("Bad character in a name"); - } - } - } - } - - - /** - * Skip characters until past the requested string. - * If it is not found, we are left at the end of the source with a result of false. - * @param to A string to skip past. - * @throws JSONException - */ - public boolean skipPast(String to) throws JSONException { - boolean b; - char c; - int i; - int j; - int offset = 0; - int length = to.length(); - char[] circle = new char[length]; - - /* - * First fill the circle buffer with as many characters as are in the - * to string. If we reach an early end, bail. - */ - - for (i = 0; i < length; i += 1) { - c = next(); - if (c == 0) { - return false; - } - circle[i] = c; - } - /* - * We will loop, possibly for all of the remaining characters. - */ - for (;;) { - j = offset; - b = true; - /* - * Compare the circle buffer with the to string. - */ - for (i = 0; i < length; i += 1) { - if (circle[j] != to.charAt(i)) { - b = false; - break; - } - j += 1; - if (j >= length) { - j -= length; - } - } - /* - * If we exit the loop with b intact, then victory is ours. - */ - if (b) { - return true; - } - /* - * Get the next character. If there isn't one, then defeat is ours. - */ - c = next(); - if (c == 0) { - return false; - } - /* - * Shove the character in the circle buffer and advance the - * circle offset. The offset is mod n. - */ - circle[offset] = c; - offset += 1; - if (offset >= length) { - offset -= length; - } - } - } -} From 2257b0bcf2a932f3a8d153232bb1fda027e8711e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 17 Aug 2012 16:33:08 -0400 Subject: [PATCH 032/140] Adding some new Java classes that need to be implemented. --- wdl/CompositeTask.java | 78 +++++++++++++++++++++++++++++++------ wdl/CompositeTaskEdge.java | 26 +++++++++++++ wdl/CompositeTaskForScope.java | 25 ++++++++++++ wdl/CompositeTaskInput.java | 25 ++++++++++++ wdl/CompositeTaskNode.java | 1 + wdl/CompositeTaskOutput.java | 37 ++++++++++++++++++ wdl/CompositeTaskScope.java | 5 +++ wdl/CompositeTaskStep.java | 33 ++++++++++++++++ wdl/CompositeTaskSubTask.java | 23 +++++++++++ wdl/CompositeTaskToDotCompiler.java | 5 +++ wdl/WdlAnsiColorizer.java | 9 +++++ wdl/WdlColorTheme.java | 5 +++ wdl/WdlHtmlColorizer.java | 9 +++++ wdl/WdlSourceCodeFormatter.java | 21 ++++++++++ wdl/WdlSourceCodeNormalizer.java | 5 +++ wdl/WdlTerminalColorizer.java | 3 ++ 16 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 wdl/CompositeTaskEdge.java create mode 100644 wdl/CompositeTaskForScope.java create mode 100644 wdl/CompositeTaskInput.java create mode 100644 wdl/CompositeTaskNode.java create mode 100644 wdl/CompositeTaskOutput.java create mode 100644 wdl/CompositeTaskScope.java create mode 100644 wdl/CompositeTaskStep.java create mode 100644 wdl/CompositeTaskSubTask.java create mode 100644 wdl/CompositeTaskToDotCompiler.java create mode 100644 wdl/WdlAnsiColorizer.java create mode 100644 wdl/WdlColorTheme.java create mode 100644 wdl/WdlHtmlColorizer.java create mode 100644 wdl/WdlSourceCodeFormatter.java create mode 100644 wdl/WdlSourceCodeNormalizer.java create mode 100644 wdl/WdlTerminalColorizer.java diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 604f91f..a11942e 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -4,12 +4,16 @@ import java.util.ArrayList; import java.util.Map; import java.util.HashMap; +import java.util.HashSet; -class CompositeTask { +class CompositeTask implements CompositeTaskScope { private ParseTree parse_tree; private Ast ast; private WdlSyntaxErrorFormatter error_formatter; + private Set nodes; + private Set edges; + private String name; private class CompositeTaskAstVerifier { private WdlSyntaxErrorFormatter syntaxErrorFormatter; @@ -68,6 +72,18 @@ private Terminal getTaskName(Ast step) { /** Constructors **/ + CompositeTask(String name, Set nodes, Set edges) { + this.name = name; + this.nodes = nodes; + this.edges = edges; + } + + CompositeTask(String name) { + this.name = name; + this.nodes = new HashSet(); + this.edges = new HashSet(); + } + CompositeTask(SourceCode source_code) throws SyntaxError { this.error_formatter = new WdlSyntaxErrorFormatter(); this.error_formatter.setSourceCode(source_code); @@ -92,20 +108,60 @@ public ParseTree getParseTree() { return this.parse_tree; } + public String getName() { + return this.name; + } + + public Set getNodes() { + return this.nodes; + } + + public Set getEdges() { + return this.edges; + } + + public CompositeTaskStep getStep(String name) { + + } + + public CompositeTaskOutput getOutput(String name) { + + } + + public Set getTasks() { + + } + + public Set getInputs() { + + } + + public Map> getDependencyGraph() { + + } + public Ast getAst() { return this.ast; } - public Map getSteps() { - Map map = new HashMap(); - AstList steps = (AstList) this.ast.getAttribute("body"); - for ( AstNode step : steps ) { - Ast step_ast = (Ast) step; - if ( step_ast.getName().equals("Step") ) { - map.put(getStepName(step_ast), step_ast); - } - } - return map; + public void setNodes(Set nodes) { + this.nodes = nodes; + } + + public void setEdges(Set edges) { + this.edges = edges; + } + + public void setName(String name) { + this.name = name; + } + + public void addEdge(CompositeTaskEdge edge) { + this.edges.add(edge); + } + + public void addNode(CompositeTaskNode node) { + this.nodes.add(node); } /** Private methods **/ diff --git a/wdl/CompositeTaskEdge.java b/wdl/CompositeTaskEdge.java new file mode 100644 index 0000000..b0c22dd --- /dev/null +++ b/wdl/CompositeTaskEdge.java @@ -0,0 +1,26 @@ +class CompositeTaskEdge { + private CompositeTaskOutput start; + private CompositeTaskInput end; + + public CompositeTaskEdge(CompositeTaskOutput start, CompositeTaskInput end) { + this.start = start; + this.end = end; + } + + public CompositeTaskOutput getStart() { + return this.start; + } + + public CompositeTaskInput getEnd() { + return this.end; + } + + /* TODO: How will these methods be implemented? */ + public int hashCode() { + + } + + public boolean equals(CompositeTaskEdge other) { + + } +} diff --git a/wdl/CompositeTaskForScope.java b/wdl/CompositeTaskForScope.java new file mode 100644 index 0000000..f05dbc6 --- /dev/null +++ b/wdl/CompositeTaskForScope.java @@ -0,0 +1,25 @@ +import java.util.Set; + +class CompositeTaskForScope implements CompositeTaskScope { + private String collection; + private String var; + private Set nodes; + + public CompositeTaskForScope(String collection, String var, Set nodes) { + this.collection = collection; + this.var = var; + this.nodes = nodes; + } + + public String getCollectionName() { + return this.collection; + } + + public String getVarName() { + return this.var; + } + + public Set getNodes() { + return this.nodes; + } +} diff --git a/wdl/CompositeTaskInput.java b/wdl/CompositeTaskInput.java new file mode 100644 index 0000000..94cb9f1 --- /dev/null +++ b/wdl/CompositeTaskInput.java @@ -0,0 +1,25 @@ +class CompositeTaskInput { + private CompositeTaskNode node; + private String name; + + public CompositeTaskInput(CompositeTaskNode node, String name) { + this.node = node; + this.name = name; + } + + public CompositeTaskNode getNode() { + return this.node; + } + + public String getName() { + return this.name; + } + + public int hashCode() { + + } + + public boolean equals(CompositeTaskInput other) { + + } +} diff --git a/wdl/CompositeTaskNode.java b/wdl/CompositeTaskNode.java new file mode 100644 index 0000000..28cc986 --- /dev/null +++ b/wdl/CompositeTaskNode.java @@ -0,0 +1 @@ +interface CompositeTaskNode {} diff --git a/wdl/CompositeTaskOutput.java b/wdl/CompositeTaskOutput.java new file mode 100644 index 0000000..dd31b59 --- /dev/null +++ b/wdl/CompositeTaskOutput.java @@ -0,0 +1,37 @@ +class CompositeTaskOutput { + private CompositeTaskNode node; + private String type; + private String path; + private String name; + + public CompositeTaskOutput(CompositeTaskNode node, String type, String path, String name) { + this.node = node; + this.type = type; + this.path = path; + this.name = name; + } + + public CompositeTaskNode getNode() { + return this.node; + } + + public String getType() { + return this.type; + } + + public String getPath() { + return this.path; + } + + public String getName() { + return this.name; + } + + public int hashCode() { + + } + + public boolean equals(CompositeTaskOutput other) { + + } +} diff --git a/wdl/CompositeTaskScope.java b/wdl/CompositeTaskScope.java new file mode 100644 index 0000000..4651dcc --- /dev/null +++ b/wdl/CompositeTaskScope.java @@ -0,0 +1,5 @@ +import java.util.Set; + +interface CompositeTaskScope extends CompositeTaskNode { + public Set getNodes(); +} diff --git a/wdl/CompositeTaskStep.java b/wdl/CompositeTaskStep.java new file mode 100644 index 0000000..87da62b --- /dev/null +++ b/wdl/CompositeTaskStep.java @@ -0,0 +1,33 @@ +import java.util.Collection; + +class CompositeTaskStep implements CompositeTaskNode { + private CompositeTaskSubTask task; + private String name; + + public CompositeTaskStep(CompositeTaskSubTask task) { + this.task = task; + this.name = task.getTaskName(); + } + + public CompositeTaskStep(String name, CompositeTaskSubTask task) { + this.task = task; + this.name = name; + } + + public String getName() { + return this.name; + } + + public CompositeTaskSubTask getTask() { + return this.task; + } + + /* TODO: Are steps only unique by name? */ + public int hashCode() { + + } + + public boolean equals(CompositeTaskStep other) { + + } +} diff --git a/wdl/CompositeTaskSubTask.java b/wdl/CompositeTaskSubTask.java new file mode 100644 index 0000000..683d9c8 --- /dev/null +++ b/wdl/CompositeTaskSubTask.java @@ -0,0 +1,23 @@ +import java.util.Set; + +class CompositeTaskSubTask { + private String name; + private String version; + + public CompositeTaskSubTask(String name, String version) { + this.name = name; + this.version = version; + } + + public String getTaskName() { + return this.name; + } + + public String getVersion() { + return this.version; + } + + public Set getInputs() { + /* TODO: implement */ + } +} diff --git a/wdl/CompositeTaskToDotCompiler.java b/wdl/CompositeTaskToDotCompiler.java new file mode 100644 index 0000000..3669ca3 --- /dev/null +++ b/wdl/CompositeTaskToDotCompiler.java @@ -0,0 +1,5 @@ +class CompositeTaskToDotCompiler { + public String compile(CompositeTask task) { + + } +} diff --git a/wdl/WdlAnsiColorizer.java b/wdl/WdlAnsiColorizer.java new file mode 100644 index 0000000..13bbbb4 --- /dev/null +++ b/wdl/WdlAnsiColorizer.java @@ -0,0 +1,9 @@ +class WdlAnsiColorizer implements WdlTerminalColorizer { + WdlHtmlColorizer(WdlColorTheme theme) { + + } + + String colorize(Terminal terminal) { + + } +} diff --git a/wdl/WdlColorTheme.java b/wdl/WdlColorTheme.java new file mode 100644 index 0000000..7d16983 --- /dev/null +++ b/wdl/WdlColorTheme.java @@ -0,0 +1,5 @@ +import java.awt.Color; + +interface WdlColorTheme { + Color getColor(Terminal terminal); +} diff --git a/wdl/WdlHtmlColorizer.java b/wdl/WdlHtmlColorizer.java new file mode 100644 index 0000000..72dfc4b --- /dev/null +++ b/wdl/WdlHtmlColorizer.java @@ -0,0 +1,9 @@ +class WdlHtmlColorizer implements WdlTerminalColorizer { + WdlHtmlColorizer(WdlColorTheme theme) { + + } + + String colorize(Terminal terminal) { + + } +} diff --git a/wdl/WdlSourceCodeFormatter.java b/wdl/WdlSourceCodeFormatter.java new file mode 100644 index 0000000..c40245c --- /dev/null +++ b/wdl/WdlSourceCodeFormatter.java @@ -0,0 +1,21 @@ +class WdlSourceCodeFormatter { + private WdlSourceColorizer colorizer; + private WdlSourceCodeNormalizer normalizer; + + WdlSourceReformatter(WdlSourceColorizer colorizer, WdlSourceCodeNormalizer normalizer) { + this.colorizer = colorizer; + this.normalizer = normalizer; + } + + WdlSourceReformatter(WdlSourceColorizer colorizer) { + this.colorizer = colorizer; + } + + WdlSourceReformatter(WdlSourceCodeNormalizer normalizer) { + this.normalizer = normalizer; + } + + public String compile(CompositeTask task) { + + } +} diff --git a/wdl/WdlSourceCodeNormalizer.java b/wdl/WdlSourceCodeNormalizer.java new file mode 100644 index 0000000..6b083ad --- /dev/null +++ b/wdl/WdlSourceCodeNormalizer.java @@ -0,0 +1,5 @@ +class WdlSourceCodeFormatter { + ParseTree format(ParseTree tree) { + + } +} diff --git a/wdl/WdlTerminalColorizer.java b/wdl/WdlTerminalColorizer.java new file mode 100644 index 0000000..d7333c6 --- /dev/null +++ b/wdl/WdlTerminalColorizer.java @@ -0,0 +1,3 @@ +interface WdlTerminalColorizer { + String colorize(Terminal terminal); +} From 17645053e98b85d3d7b11899919e665450710356 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 17 Aug 2012 16:39:42 -0400 Subject: [PATCH 033/140] Fixing some errors --- wdl/CompositeTask.java | 3 +-- wdl/WdlAnsiColorizer.java | 4 ++-- wdl/WdlHtmlColorizer.java | 2 +- wdl/WdlMain.java | 5 +---- wdl/WdlSourceCodeFormatter.java | 8 ++++---- wdl/WdlSourceCodeNormalizer.java | 2 +- 6 files changed, 10 insertions(+), 14 deletions(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index a11942e..80a2c57 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -1,9 +1,8 @@ import java.io.File; import java.io.IOException; import java.util.List; -import java.util.ArrayList; import java.util.Map; -import java.util.HashMap; +import java.util.Set; import java.util.HashSet; class CompositeTask implements CompositeTaskScope { diff --git a/wdl/WdlAnsiColorizer.java b/wdl/WdlAnsiColorizer.java index 13bbbb4..f68847e 100644 --- a/wdl/WdlAnsiColorizer.java +++ b/wdl/WdlAnsiColorizer.java @@ -1,9 +1,9 @@ class WdlAnsiColorizer implements WdlTerminalColorizer { - WdlHtmlColorizer(WdlColorTheme theme) { + WdlAnsiColorizer(WdlColorTheme theme) { } - String colorize(Terminal terminal) { + public String colorize(Terminal terminal) { } } diff --git a/wdl/WdlHtmlColorizer.java b/wdl/WdlHtmlColorizer.java index 72dfc4b..3208e3b 100644 --- a/wdl/WdlHtmlColorizer.java +++ b/wdl/WdlHtmlColorizer.java @@ -3,7 +3,7 @@ } - String colorize(Terminal terminal) { + public String colorize(Terminal terminal) { } } diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index abe52ac..19a6975 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -26,10 +26,7 @@ public static void main(String[] args) { ParseTree tree = wdl.getParseTree(); System.out.println(tree.toPrettyString()); } else if ( args[1].equals("nodes") ) { - Map steps = wdl.getSteps(); - for ( Map.Entry entry : steps.entrySet() ) { - System.out.println("Step: " + entry.getKey()); - } + // TODO: implement } else { usage(); } diff --git a/wdl/WdlSourceCodeFormatter.java b/wdl/WdlSourceCodeFormatter.java index c40245c..cdaa53d 100644 --- a/wdl/WdlSourceCodeFormatter.java +++ b/wdl/WdlSourceCodeFormatter.java @@ -1,17 +1,17 @@ class WdlSourceCodeFormatter { - private WdlSourceColorizer colorizer; + private WdlTerminalColorizer colorizer; private WdlSourceCodeNormalizer normalizer; - WdlSourceReformatter(WdlSourceColorizer colorizer, WdlSourceCodeNormalizer normalizer) { + WdlSourceCodeFormatter(WdlTerminalColorizer colorizer, WdlSourceCodeNormalizer normalizer) { this.colorizer = colorizer; this.normalizer = normalizer; } - WdlSourceReformatter(WdlSourceColorizer colorizer) { + WdlSourceCodeFormatter(WdlTerminalColorizer colorizer) { this.colorizer = colorizer; } - WdlSourceReformatter(WdlSourceCodeNormalizer normalizer) { + WdlSourceCodeFormatter(WdlSourceCodeNormalizer normalizer) { this.normalizer = normalizer; } diff --git a/wdl/WdlSourceCodeNormalizer.java b/wdl/WdlSourceCodeNormalizer.java index 6b083ad..af3b3a4 100644 --- a/wdl/WdlSourceCodeNormalizer.java +++ b/wdl/WdlSourceCodeNormalizer.java @@ -1,4 +1,4 @@ -class WdlSourceCodeFormatter { +class WdlSourceCodeNormalizer { ParseTree format(ParseTree tree) { } From 9fc7576fc395b501b4e8c702589e4608f53fd7d2 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 17 Aug 2012 16:42:10 -0400 Subject: [PATCH 034/140] moving files around --- wdl/CopyNumberQCReport.wdl | 6 ------ wdl/{ => examples}/CopyNumberQC.wdl | 0 wdl/{ => examples}/MutSig.wdl | 0 wdl/{ => examples}/simple.wdl | 0 4 files changed, 6 deletions(-) delete mode 100644 wdl/CopyNumberQCReport.wdl rename wdl/{ => examples}/CopyNumberQC.wdl (100%) rename wdl/{ => examples}/MutSig.wdl (100%) rename wdl/{ => examples}/simple.wdl (100%) diff --git a/wdl/CopyNumberQCReport.wdl b/wdl/CopyNumberQCReport.wdl deleted file mode 100644 index 74d0b6e..0000000 --- a/wdl/CopyNumberQCReport.wdl +++ /dev/null @@ -1,6 +0,0 @@ -task CopyNumberQCReport { - action: command("python run_matlab.py --with-display fh_CopyNumberQCReport "); - version: "1.4.2"; - description: "does CopyNumberQCReport"; - ... -} diff --git a/wdl/CopyNumberQC.wdl b/wdl/examples/CopyNumberQC.wdl similarity index 100% rename from wdl/CopyNumberQC.wdl rename to wdl/examples/CopyNumberQC.wdl diff --git a/wdl/MutSig.wdl b/wdl/examples/MutSig.wdl similarity index 100% rename from wdl/MutSig.wdl rename to wdl/examples/MutSig.wdl diff --git a/wdl/simple.wdl b/wdl/examples/simple.wdl similarity index 100% rename from wdl/simple.wdl rename to wdl/examples/simple.wdl From 62191e1027a6c449344b6985565cb8336f7447df Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 17 Aug 2012 16:54:18 -0400 Subject: [PATCH 035/140] WiP --- wdl/CompositeTask.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 80a2c57..1d31033 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -120,7 +120,15 @@ public String getName() { } public CompositeTaskStep getStep(String name) { - + for ( CompositeTaskNode node : this.nodes ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + if ( step.getName.equals(name) ) { + return step; + } + } + } + return null; } public CompositeTaskOutput getOutput(String name) { From 7ce91ed55c9f4734806b7bffb76a51a44f7d58e5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sun, 19 Aug 2012 10:46:18 -0400 Subject: [PATCH 036/140] more work on the Java front-end --- wdl/CompositeTask.java | 302 +++++++++++++++++++++++++++++++++--- wdl/CompositeTaskEdge.java | 14 +- wdl/CompositeTaskForScope.java | 15 ++ wdl/CompositeTaskInput.java | 21 ++- wdl/CompositeTaskNode.java | 4 +- wdl/CompositeTaskOutput.java | 16 +- wdl/CompositeTaskStep.java | 22 ++- wdl/CompositeTaskSubTask.java | 1 + wdl/CompositeTaskToDotCompiler.java | 2 +- wdl/WdlAnsiColorizer.java | 4 +- wdl/WdlHtmlColorizer.java | 2 +- wdl/WdlMain.java | 15 +- wdl/WdlSourceCodeFormatter.java | 2 +- wdl/WdlSourceCodeNormalizer.java | 2 +- wdl/examples/0.wdl | 24 +++ wdl/examples/1.wdl | 39 +++++ wdl/examples/CopyNumberQC.wdl | 6 +- 17 files changed, 431 insertions(+), 60 deletions(-) create mode 100644 wdl/examples/0.wdl create mode 100644 wdl/examples/1.wdl diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 1d31033..25761b2 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -4,6 +4,8 @@ import java.util.Map; import java.util.Set; import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; class CompositeTask implements CompositeTaskScope { @@ -12,6 +14,7 @@ private WdlSyntaxErrorFormatter error_formatter; private Set nodes; private Set edges; + private Set inputs; private String name; private class CompositeTaskAstVerifier { @@ -39,39 +42,281 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { */ AstList steps = (AstList) composite_task.getAttribute("body"); + for ( AstNode step : steps ) { Ast step_ast = (Ast) step; - Ast task = (Ast) step_ast.getAttribute("task"); - AstList task_attrs = (AstList) task.getAttribute("attributes"); + if ( step_ast.getName().equals("Step") ) { + CompositeTask.this.nodes.add( verify_step(step_ast) ); + } else if ( step_ast.getName().equals("ForLoop") ) { + CompositeTask.this.nodes.add( verify_for(step_ast) ); + } + } - boolean version_found = false; + /* outputs: Map of String variable_name -> Set which represents a set of + * entities that write an output to that variable. e.g. output: File("foo.txt") as bar would + * add an entry to outputs at key 'bar'. No two outputs should write to the same variable. + * + * inputs: Map of String variable_name -> Set which represents the set of + * nodes that need variable_name as a prerequisite. Note that this also includes Scope nodes + * like 'for' or 'composite_task' nodes. Also note that get_node_inputs() actually generates + * scope inputs based on the union of all of the inputs of its sub-nodes, which isn't terribly + * useful because a lot of those could be satisfied internally. For example: + * + * composite_task test { + * step foo[version=0] { + * output: File("foo.txt") as bar + * } + * + * step baz[version=0] { + * input: x=bar, y=var + * } + * } + * + * the composite task will have inputs bar and var (on top of the inputs from step foo and baz). + * However, 'bar' is already satisfied by step foo so the composite task really only needs 'foo' + */ + Map> outputs = get_node_outputs(CompositeTask.this); + Map> inputs = get_node_inputs(CompositeTask.this); + + /* Map outputs -> inputs, creating the edges in the graph */ + for ( Map.Entry> entry : outputs.entrySet() ) { + String variable = entry.getKey(); + Set output_set = entry.getValue(); + for ( CompositeTaskOutput output: output_set ) { + if ( output.getNode() == CompositeTask.this ) { + continue; + } + if ( inputs.get(variable) != null ) { + for ( CompositeTaskInput input : inputs.get(variable) ) { + if ( input.getNode() == CompositeTask.this ) { + continue; + } + if ( input.getNode() != output.getNode() ) { + CompositeTaskEdge edge = new CompositeTaskEdge(output, input, variable); + CompositeTask.this.edges.add(edge); + } + } + } + } + } - if ( task_attrs != null ) { - for ( AstNode task_attr : task_attrs ) { - Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); - if ( key.getSourceString().equals("version") ) { - version_found = true; + for ( Map.Entry> entry : inputs.entrySet() ) { + Set in_set = entry.getValue(); + String variable = entry.getKey(); + + Iterator iter = in_set.iterator(); + while (iter.hasNext()) { + CompositeTaskInput in = iter.next(); + if ( in.getNode() instanceof CompositeTaskScope ) { + if ( outputs_variable(in.getNode(), variable) ) { + iter.remove(); } } } + } - if ( version_found == false ) { - Terminal task_name = getTaskName(step_ast); - throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); + for ( Map.Entry> entry : inputs.entrySet() ) { + String variable = entry.getKey(); + Set ins = entry.getValue(); + for ( CompositeTaskInput input : ins ) { + if ( input.getNode() == CompositeTask.this ) { + CompositeTask.this.inputs.add(variable); + } } + System.out.println("INPUT " + entry.getKey() + " --- " + Utility.join(entry.getValue(), ", ")); } return composite_task; } - private Terminal getTaskName(Ast step) { - return (Terminal) ((Ast)step.getAttribute("task")).getAttribute("name"); + private boolean outputs_variable(CompositeTaskNode node, String variable) { + if (node instanceof CompositeTaskScope) { + CompositeTaskScope scope = (CompositeTaskScope) node; + boolean answer = false; + for ( CompositeTaskNode scope_node : scope.getNodes() ) { + answer |= outputs_variable(scope_node, variable); + } + return answer; + } else if (node instanceof CompositeTaskStep) { + CompositeTaskStep step = (CompositeTaskStep) node; + for ( CompositeTaskEdge edge : CompositeTask.this.edges ) { + if ( edge.getVariable().equals(variable) && edge.getStart().getNode() == step) { + return true; + } + } + } + return false; + } + + private String variable_to_string(Ast variable) { + String name; + Terminal asName = (Terminal) variable.getAttribute("name"); + Terminal asMember = (Terminal) variable.getAttribute("member"); + name = asName.getSourceString(); + + if ( false && asMember != null ) { + name += "." + asMember.getSourceString(); + } + return name; + } + + private Map> get_node_inputs(CompositeTaskNode node) throws SyntaxError { + Map> inputs = new HashMap>(); + if ( node instanceof CompositeTaskStep ) { + AstList node_body = (AstList) node.getAst().getAttribute("body"); + for ( AstNode elem : node_body ) { + if ( elem instanceof Ast && ((Ast) elem).getName().equals("StepInputList") ) { + for ( AstNode input_node : (AstList) ((Ast) elem).getAttribute("inputs") ) { + Ast input = (Ast) input_node; + if ( input.getName().equals("StepInput") ) { + String parameter = ((Terminal) input.getAttribute("parameter")).getSourceString(); + String variable = variable_to_string((Ast) input.getAttribute("value")); + if ( !inputs.containsKey(variable) ) { + inputs.put(variable, new HashSet()); + } + inputs.get(variable).add( new CompositeTaskInput(node, parameter) ); + } + } + } + } + } else if ( node instanceof CompositeTaskScope ) { + /* TODO: just change the behavior of this loop to include Scopes in the */ + for ( CompositeTaskNode sub_node : ((CompositeTaskScope) node).getNodes() ) { + for ( Map.Entry> input : get_node_inputs(sub_node).entrySet() ) { + String variable = input.getKey(); + Set in = input.getValue(); + + if ( !inputs.containsKey(variable) ) { + inputs.put(variable, new HashSet()); + } + + inputs.get(variable).addAll(in); + inputs.get(variable).add(new CompositeTaskInput(node)); + } + } + + if ( node instanceof CompositeTaskForScope ) { + String collection = ((CompositeTaskForScope) node).getCollectionName(); + if ( !inputs.containsKey(collection) ) { + inputs.put(collection, new HashSet()); + } + inputs.get(collection).add(new CompositeTaskInput(node)); + } + } + return inputs; + } + + private Map> get_node_outputs(CompositeTaskNode node) throws SyntaxError { + Map> outputs = new HashMap>(); + if ( node instanceof CompositeTaskStep ) { + AstList node_body = (AstList) node.getAst().getAttribute("body"); + for ( AstNode elem : node_body ) { + if ( elem instanceof Ast && ((Ast) elem).getName().equals("StepOutputList") ) { + for ( AstNode output_node : (AstList) ((Ast) elem).getAttribute("outputs") ) { + Ast output = (Ast) output_node; + if ( output.getName().equals("StepFileOutput") ) { + String file_path = ((Terminal) output.getAttribute("file")).getSourceString(); + String variable = variable_to_string((Ast) output.getAttribute("as")); + if ( !outputs.containsKey(variable) ) { + outputs.put(variable, new HashSet()); + } + outputs.get(variable).add( new CompositeTaskOutput(node, "File", file_path) ); + } + } + } + } + } else if ( node instanceof CompositeTaskScope ) { + Map scope_outputs = new HashMap(); + for ( CompositeTaskNode sub_node : ((CompositeTaskScope) node).getNodes() ) { + for ( Map.Entry> output : get_node_outputs(sub_node).entrySet() ) { + String variable = output.getKey(); + Set out = output.getValue(); + if ( !outputs.containsKey(variable) ) { + outputs.put(variable, new HashSet()); + } + + outputs.get(variable).addAll(out); + + for ( CompositeTaskOutput o : out ) { + if ( !scope_outputs.containsKey(variable) ) { + scope_outputs.put(variable, new CompositeTaskOutput(node, o.getType(), o.getPath())); + } + } + } + } + + for ( Map.Entry entry : scope_outputs.entrySet() ) { + outputs.get(entry.getKey()).add(entry.getValue()); + } + } + return outputs; + } + + private CompositeTaskNode verify_step(Ast step) throws SyntaxError { + Ast task = (Ast) step.getAttribute("task"); + Terminal task_name = getTaskName(task); + Terminal task_version = getTaskVersion(task); + + if ( task_version == null ) { + throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); + } + + CompositeTaskSubTask ctSubTask = new CompositeTaskSubTask( + task_name.getSourceString(), + task_version.getSourceString() + ); + + String ctStepName; + if ( step.getAttribute("name") != null ) { + ctStepName = ((Terminal) step.getAttribute("name")).getSourceString(); + } else { + ctStepName = task_name.getSourceString(); + } + + return new CompositeTaskStep(step, ctStepName, ctSubTask); + } + + private CompositeTaskNode verify_for(Ast for_node_ast) throws SyntaxError { + Set nodes = new HashSet(); + + for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { + Ast for_sub_node_ast = (Ast) for_sub_node; + if ( for_sub_node_ast.getName().equals("ForLoop") ) { + nodes.add(verify_for(for_sub_node_ast)); + } else if (for_sub_node_ast.getName().equals("Step")) { + nodes.add(verify_step(for_sub_node_ast)); + } + } + + String collection = ((Terminal)for_node_ast.getAttribute("collection")).getSourceString(); + String item = ((Terminal)for_node_ast.getAttribute("item")).getSourceString(); + + return new CompositeTaskForScope(for_node_ast, collection, item, nodes); + } + + private Terminal getTaskName(Ast task) { + return (Terminal) task.getAttribute("name"); + } + + private Terminal getTaskVersion(Ast task) { + AstList task_attrs = (AstList) task.getAttribute("attributes"); + + if ( task_attrs != null ) { + for ( AstNode task_attr : task_attrs ) { + Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); + if ( key.getSourceString().equals("version") ) { + return key; + } + } + } + + return null; } } /** Constructors **/ - CompositeTask(String name, Set nodes, Set edges) { + CompositeTask(String name, Set nodes, Set edges, Set inputs) { this.name = name; this.nodes = nodes; this.edges = edges; @@ -81,6 +326,7 @@ private Terminal getTaskName(Ast step) { this.name = name; this.nodes = new HashSet(); this.edges = new HashSet(); + this.inputs = new HashSet(); } CompositeTask(SourceCode source_code) throws SyntaxError { @@ -90,6 +336,9 @@ private Terminal getTaskName(Ast step) { this.parse_tree = (ParseTree) node; AstList ast_list = (AstList) node.toAst(); CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); + this.nodes = new HashSet(); + this.edges = new HashSet(); + this.inputs = new HashSet(); this.ast = verifier.verify(ast_list); } @@ -123,7 +372,7 @@ public CompositeTaskStep getStep(String name) { for ( CompositeTaskNode node : this.nodes ) { if ( node instanceof CompositeTaskStep ) { CompositeTaskStep step = (CompositeTaskStep) node; - if ( step.getName.equals(name) ) { + if ( step.getName().equals(name) ) { return step; } } @@ -132,19 +381,29 @@ public CompositeTaskStep getStep(String name) { } public CompositeTaskOutput getOutput(String name) { - + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getVariable().equals(name) ) { + return edge.getStart(); + } + } + return null; } public Set getTasks() { - + return null; } public Set getInputs() { - + // Per task: + // 1) get input variables for task + // 2) remove 'parameter' value for all edges with to=task + // Named inputs + // add for loop collection values + return this.inputs; } public Map> getDependencyGraph() { - + return null; } public Ast getAst() { @@ -172,11 +431,6 @@ public void addNode(CompositeTaskNode node) { } /** Private methods **/ - private String getStepName(Ast step) { - Terminal name = (Terminal) step.getAttribute("name"); - Terminal task_name = (Terminal) ((Ast)step.getAttribute("task")).getAttribute("name"); - return (name != null) ? name.getSourceString() : task_name.getSourceString(); - } private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { WdlParser parser = new WdlParser(this.error_formatter); diff --git a/wdl/CompositeTaskEdge.java b/wdl/CompositeTaskEdge.java index b0c22dd..9b46a13 100644 --- a/wdl/CompositeTaskEdge.java +++ b/wdl/CompositeTaskEdge.java @@ -1,10 +1,12 @@ class CompositeTaskEdge { private CompositeTaskOutput start; private CompositeTaskInput end; + private String variable; - public CompositeTaskEdge(CompositeTaskOutput start, CompositeTaskInput end) { + public CompositeTaskEdge(CompositeTaskOutput start, CompositeTaskInput end, String variable) { this.start = start; this.end = end; + this.variable = variable; } public CompositeTaskOutput getStart() { @@ -15,12 +17,20 @@ public CompositeTaskInput getEnd() { return this.end; } + public String getVariable() { + return this.variable; + } + /* TODO: How will these methods be implemented? */ public int hashCode() { - + return 0; } public boolean equals(CompositeTaskEdge other) { + return false; + } + public String toString() { + return "[Edge\n from="+this.start+",\n to="+this.end+",\n var="+this.variable+"\n]"; } } diff --git a/wdl/CompositeTaskForScope.java b/wdl/CompositeTaskForScope.java index f05dbc6..30691fa 100644 --- a/wdl/CompositeTaskForScope.java +++ b/wdl/CompositeTaskForScope.java @@ -4,13 +4,24 @@ private String collection; private String var; private Set nodes; + private Ast ast; public CompositeTaskForScope(String collection, String var, Set nodes) { + this.ast = null; this.collection = collection; this.var = var; this.nodes = nodes; } + public CompositeTaskForScope(Ast ast, String collection, String var, Set nodes) { + this(collection, var, nodes); + this.ast = ast; + } + + public Ast getAst() { + return this.ast; + } + public String getCollectionName() { return this.collection; } @@ -22,4 +33,8 @@ public String getVarName() { public Set getNodes() { return this.nodes; } + + public String toString() { + return "[CompositeTaskForScope: collection=" + this.collection + ", var=" + this.var + ", # nodes=" + this.nodes.size()+ "]"; + } } diff --git a/wdl/CompositeTaskInput.java b/wdl/CompositeTaskInput.java index 94cb9f1..043f51f 100644 --- a/wdl/CompositeTaskInput.java +++ b/wdl/CompositeTaskInput.java @@ -1,25 +1,34 @@ class CompositeTaskInput { private CompositeTaskNode node; - private String name; + private String parameter; - public CompositeTaskInput(CompositeTaskNode node, String name) { + public CompositeTaskInput(CompositeTaskNode node) { this.node = node; - this.name = name; + this.parameter = null; + } + + public CompositeTaskInput(CompositeTaskNode node, String parameter) { + this(node); + this.parameter = parameter; } public CompositeTaskNode getNode() { return this.node; } - public String getName() { - return this.name; + public String getParameter() { + return this.parameter; } public int hashCode() { - + return 0; } public boolean equals(CompositeTaskInput other) { + return false; + } + public String toString() { + return "[Input node="+this.node+", param="+this.parameter+"]"; } } diff --git a/wdl/CompositeTaskNode.java b/wdl/CompositeTaskNode.java index 28cc986..5e301f3 100644 --- a/wdl/CompositeTaskNode.java +++ b/wdl/CompositeTaskNode.java @@ -1 +1,3 @@ -interface CompositeTaskNode {} +interface CompositeTaskNode { + public Ast getAst(); +} diff --git a/wdl/CompositeTaskOutput.java b/wdl/CompositeTaskOutput.java index dd31b59..b939238 100644 --- a/wdl/CompositeTaskOutput.java +++ b/wdl/CompositeTaskOutput.java @@ -2,13 +2,11 @@ private CompositeTaskNode node; private String type; private String path; - private String name; - public CompositeTaskOutput(CompositeTaskNode node, String type, String path, String name) { + public CompositeTaskOutput(CompositeTaskNode node, String type, String path) { this.node = node; this.type = type; this.path = path; - this.name = name; } public CompositeTaskNode getNode() { @@ -23,15 +21,15 @@ public String getPath() { return this.path; } - public String getName() { - return this.name; - } - public int hashCode() { - + return 0; } public boolean equals(CompositeTaskOutput other) { - + return false; + } + + public String toString() { + return "[Output node="+this.node+", path="+this.path+"]"; } } diff --git a/wdl/CompositeTaskStep.java b/wdl/CompositeTaskStep.java index 87da62b..aae2735 100644 --- a/wdl/CompositeTaskStep.java +++ b/wdl/CompositeTaskStep.java @@ -3,17 +3,23 @@ class CompositeTaskStep implements CompositeTaskNode { private CompositeTaskSubTask task; private String name; - - public CompositeTaskStep(CompositeTaskSubTask task) { - this.task = task; - this.name = task.getTaskName(); - } + private Ast ast; public CompositeTaskStep(String name, CompositeTaskSubTask task) { + this.ast = null; this.task = task; this.name = name; } + public CompositeTaskStep(Ast ast, String name, CompositeTaskSubTask task) { + this(name, task); + this.ast = ast; + } + + public Ast getAst() { + return this.ast; + } + public String getName() { return this.name; } @@ -24,10 +30,14 @@ public CompositeTaskSubTask getTask() { /* TODO: Are steps only unique by name? */ public int hashCode() { - + return 0; } public boolean equals(CompositeTaskStep other) { + return false; + } + public String toString() { + return "[Step: name=" + this.name + "]"; } } diff --git a/wdl/CompositeTaskSubTask.java b/wdl/CompositeTaskSubTask.java index 683d9c8..2618935 100644 --- a/wdl/CompositeTaskSubTask.java +++ b/wdl/CompositeTaskSubTask.java @@ -19,5 +19,6 @@ public String getVersion() { public Set getInputs() { /* TODO: implement */ + return null; } } diff --git a/wdl/CompositeTaskToDotCompiler.java b/wdl/CompositeTaskToDotCompiler.java index 3669ca3..eb29fe9 100644 --- a/wdl/CompositeTaskToDotCompiler.java +++ b/wdl/CompositeTaskToDotCompiler.java @@ -1,5 +1,5 @@ class CompositeTaskToDotCompiler { public String compile(CompositeTask task) { - + return null; } } diff --git a/wdl/WdlAnsiColorizer.java b/wdl/WdlAnsiColorizer.java index f68847e..03dbe9d 100644 --- a/wdl/WdlAnsiColorizer.java +++ b/wdl/WdlAnsiColorizer.java @@ -1,9 +1,9 @@ class WdlAnsiColorizer implements WdlTerminalColorizer { WdlAnsiColorizer(WdlColorTheme theme) { - + } public String colorize(Terminal terminal) { - + return null; } } diff --git a/wdl/WdlHtmlColorizer.java b/wdl/WdlHtmlColorizer.java index 3208e3b..ed32849 100644 --- a/wdl/WdlHtmlColorizer.java +++ b/wdl/WdlHtmlColorizer.java @@ -4,6 +4,6 @@ } public String colorize(Terminal terminal) { - + return null; } } diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index 19a6975..4d61849 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -2,11 +2,12 @@ import java.io.IOException; import java.util.List; import java.util.Map; +import java.util.Set; class WdlMain { public static void usage() { - System.err.println("Usage: java ParserMain <.wdl file> "); + System.err.println("Usage: java ParserMain <.wdl file> "); System.exit(-1); } @@ -25,8 +26,16 @@ public static void main(String[] args) { } else if ( args[1].equals("parsetree") ) { ParseTree tree = wdl.getParseTree(); System.out.println(tree.toPrettyString()); - } else if ( args[1].equals("nodes") ) { - // TODO: implement + } else if ( args[1].equals("graph") ) { + for ( CompositeTaskNode node : wdl.getNodes() ) { + System.out.println(node); + } + for ( CompositeTaskEdge edge : wdl.getEdges() ) { + System.out.println(edge); + } + for ( String input : wdl.getInputs() ) { + System.out.println("input: " + input); + } } else { usage(); } diff --git a/wdl/WdlSourceCodeFormatter.java b/wdl/WdlSourceCodeFormatter.java index cdaa53d..92322da 100644 --- a/wdl/WdlSourceCodeFormatter.java +++ b/wdl/WdlSourceCodeFormatter.java @@ -16,6 +16,6 @@ } public String compile(CompositeTask task) { - + return null; } } diff --git a/wdl/WdlSourceCodeNormalizer.java b/wdl/WdlSourceCodeNormalizer.java index af3b3a4..45400ea 100644 --- a/wdl/WdlSourceCodeNormalizer.java +++ b/wdl/WdlSourceCodeNormalizer.java @@ -1,5 +1,5 @@ class WdlSourceCodeNormalizer { ParseTree format(ParseTree tree) { - + return null; } } diff --git a/wdl/examples/0.wdl b/wdl/examples/0.wdl new file mode 100644 index 0000000..a699ba7 --- /dev/null +++ b/wdl/examples/0.wdl @@ -0,0 +1,24 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=s; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=y; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/wdl/examples/1.wdl b/wdl/examples/1.wdl new file mode 100644 index 0000000..4d9611b --- /dev/null +++ b/wdl/examples/1.wdl @@ -0,0 +1,39 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=global0; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=y; + output: File("quux.txt") as z; + } + + for ( alpha in beta ) { + step dtask[version=0] { + input: p0=y; + } + + composite_task foo_sub { + step etask[version=0] { + input: p0=global1, p1=y; + } + step ftask[version=0] { + input: p0=global1, p1=z; + } + } + } + } + + step gtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/wdl/examples/CopyNumberQC.wdl b/wdl/examples/CopyNumberQC.wdl index e4b3c98..8f4790d 100644 --- a/wdl/examples/CopyNumberQC.wdl +++ b/wdl/examples/CopyNumberQC.wdl @@ -6,16 +6,16 @@ composite_task CopyNumberQC { for ( sample in samples ) { step MakeLaneList[version=11] as foobar { input: bam=sample.bam, id=sample.id, regions=sample.regions; - output: File("${sample.id}.lanelist") as sample.lanelist; + output: File("${sample.id}.lanelist") as lanelist; } step RegionCovPerLane[version=16] { input: bam=sample.bam, id=sample.id, regions=sample.regions; - output: File("${sample.id}.rcl") as sample.rcl; + output: File("${sample.id}.rcl") as rcl; } } step CopyNumberQC[version=25] { - input: lanelist=samples.lanelist, rcl=samples.rcl, lane_blacklist=lane_blacklist; + input: lanelist=lanelist, rcl=rcl, lane_blacklist=lane_blacklist; } } From d27e8ab27e45714002c853b83a0230e848a947f2 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Sun, 19 Aug 2012 21:26:28 -0400 Subject: [PATCH 037/140] First version of API --- wdl/CompositeTask.java | 117 +++- wdl/CompositeTaskBaseScope.java | 19 + wdl/CompositeTaskSubTask.java | 4 + wdl/WdlMain.java | 3 + wdl/WdlParser.java | 1376 +++++++++++++++++++-------------------- wdl/wdl.zgr | 4 +- 6 files changed, 792 insertions(+), 731 deletions(-) create mode 100644 wdl/CompositeTaskBaseScope.java diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 25761b2..7d04903 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -25,15 +25,23 @@ } public Ast verify(AstNode wdl_ast) throws SyntaxError { - if ( !(wdl_ast instanceof AstList) ) { - throw new SyntaxError("Ast is not a list"); - } + Ast composite_task = null; - if ( ((AstList) wdl_ast).size() != 1 ) { - throw new SyntaxError("Composite Task definition should contain only one top level composite_task definition."); - } + if ( wdl_ast instanceof AstList ) { + if ( ((AstList) wdl_ast).size() != 1 ) { + throw new SyntaxError("Composite Task definition should contain only one top level composite_task definition."); + } - Ast composite_task = (Ast) ((AstList) wdl_ast).get(0); + composite_task = (Ast) ((AstList) wdl_ast).get(0); + } else if (wdl_ast instanceof Ast) { + composite_task = (Ast) wdl_ast; + String node_type = composite_task.getName(); + if (!node_type.equals("CompositeTask")) { + throw new SyntaxError("TODO"); + } + } else { + throw new SyntaxError("TODO"); + } /* a) Error on two 'input' or 'output' in a Step * b) Step names are unique in their scope (global or for) @@ -44,12 +52,7 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { AstList steps = (AstList) composite_task.getAttribute("body"); for ( AstNode step : steps ) { - Ast step_ast = (Ast) step; - if ( step_ast.getName().equals("Step") ) { - CompositeTask.this.nodes.add( verify_step(step_ast) ); - } else if ( step_ast.getName().equals("ForLoop") ) { - CompositeTask.this.nodes.add( verify_for(step_ast) ); - } + CompositeTask.this.nodes.add( verify((Ast) step) ); } /* outputs: Map of String variable_name -> Set which represents a set of @@ -86,15 +89,24 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { if ( output.getNode() == CompositeTask.this ) { continue; } - if ( inputs.get(variable) != null ) { + if ( inputs.get(variable) != null ) { for ( CompositeTaskInput input : inputs.get(variable) ) { if ( input.getNode() == CompositeTask.this ) { continue; } - if ( input.getNode() != output.getNode() ) { - CompositeTaskEdge edge = new CompositeTaskEdge(output, input, variable); - CompositeTask.this.edges.add(edge); + if ( input.getNode() == output.getNode() ) { + continue; + } + if ( output.getNode() instanceof CompositeTaskScope && + in_scope((CompositeTaskScope) output.getNode(), input.getNode()) ) { + continue; } + if ( input.getNode() instanceof CompositeTaskScope && + in_scope((CompositeTaskScope) input.getNode(), output.getNode()) ) { + continue; + } + CompositeTaskEdge edge = new CompositeTaskEdge(output, input, variable); + CompositeTask.this.edges.add(edge); } } } @@ -123,12 +135,22 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { CompositeTask.this.inputs.add(variable); } } - System.out.println("INPUT " + entry.getKey() + " --- " + Utility.join(entry.getValue(), ", ")); } return composite_task; } + private boolean in_scope(CompositeTaskScope scope, CompositeTaskNode node) { + boolean answer = false; + for ( CompositeTaskNode scope_node : scope.getNodes() ) { + answer |= (node == scope_node); + if ( scope_node instanceof CompositeTaskScope ) { + answer |= in_scope((CompositeTaskScope) scope_node, node); + } + } + return answer; + } + private boolean outputs_variable(CompositeTaskNode node, String variable) { if (node instanceof CompositeTaskScope) { CompositeTaskScope scope = (CompositeTaskScope) node; @@ -252,6 +274,18 @@ private String variable_to_string(Ast variable) { return outputs; } + private CompositeTaskNode verify(Ast ast) throws SyntaxError { + if ( ast.getName().equals("Step") ) { + return verify_step(ast); + } else if ( ast.getName().equals("ForLoop") ) { + return verify_for(ast); + } else if ( ast.getName().equals("CompositeTask") ) { + return verify_composite_task(ast); + } else { + throw new SyntaxError("TODO"); + } + } + private CompositeTaskNode verify_step(Ast step) throws SyntaxError { Ast task = (Ast) step.getAttribute("task"); Terminal task_name = getTaskName(task); @@ -280,20 +314,25 @@ private CompositeTaskNode verify_for(Ast for_node_ast) throws SyntaxError { Set nodes = new HashSet(); for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { - Ast for_sub_node_ast = (Ast) for_sub_node; - if ( for_sub_node_ast.getName().equals("ForLoop") ) { - nodes.add(verify_for(for_sub_node_ast)); - } else if (for_sub_node_ast.getName().equals("Step")) { - nodes.add(verify_step(for_sub_node_ast)); - } + nodes.add( verify((Ast) for_sub_node) ); } - String collection = ((Terminal)for_node_ast.getAttribute("collection")).getSourceString(); - String item = ((Terminal)for_node_ast.getAttribute("item")).getSourceString(); + String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); + String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); return new CompositeTaskForScope(for_node_ast, collection, item, nodes); } + private CompositeTaskNode verify_composite_task(Ast ast) throws SyntaxError { + Set nodes = new HashSet(); + + for ( AstNode sub : (AstList) ast.getAttribute("body") ) { + nodes.add( verify((Ast) sub) ); + } + + return new CompositeTaskBaseScope(ast, nodes); + } + private Terminal getTaskName(Ast task) { return (Terminal) task.getAttribute("name"); } @@ -304,8 +343,9 @@ private Terminal getTaskVersion(Ast task) { if ( task_attrs != null ) { for ( AstNode task_attr : task_attrs ) { Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); + Terminal value = (Terminal) ((Ast) task_attr).getAttribute("value"); if ( key.getSourceString().equals("version") ) { - return key; + return value; } } } @@ -320,6 +360,7 @@ private Terminal getTaskVersion(Ast task) { this.name = name; this.nodes = nodes; this.edges = edges; + this.inputs = inputs; } CompositeTask(String name) { @@ -390,7 +431,27 @@ public CompositeTaskOutput getOutput(String name) { } public Set getTasks() { - return null; + Set tasks = new HashSet(); + for (CompositeTaskNode node : this.nodes) { + if ( node instanceof CompositeTaskStep ) { + tasks.add( ((CompositeTaskStep) node).getTask() ); + } else if ( node instanceof CompositeTaskScope ) { + tasks.addAll( getTasks((CompositeTaskScope) node)); + } + } + return tasks; + } + + private Set getTasks(CompositeTaskScope scope) { + Set tasks = new HashSet(); + for (CompositeTaskNode node : scope.getNodes()) { + if ( node instanceof CompositeTaskStep ) { + tasks.add( ((CompositeTaskStep) node).getTask() ); + } else if ( node instanceof CompositeTaskScope ) { + tasks.addAll( getTasks((CompositeTaskScope) node)); + } + } + return tasks; } public Set getInputs() { diff --git a/wdl/CompositeTaskBaseScope.java b/wdl/CompositeTaskBaseScope.java new file mode 100644 index 0000000..5729b0c --- /dev/null +++ b/wdl/CompositeTaskBaseScope.java @@ -0,0 +1,19 @@ +import java.util.Set; + +class CompositeTaskBaseScope implements CompositeTaskScope { + private Set nodes; + private Ast ast; + + CompositeTaskBaseScope(Ast ast, Set nodes) { + this.ast = ast; + this.nodes = nodes; + } + + public Set getNodes() { + return this.nodes; + } + + public Ast getAst() { + return this.ast; + } +} diff --git a/wdl/CompositeTaskSubTask.java b/wdl/CompositeTaskSubTask.java index 2618935..88f37b6 100644 --- a/wdl/CompositeTaskSubTask.java +++ b/wdl/CompositeTaskSubTask.java @@ -21,4 +21,8 @@ public String getVersion() { /* TODO: implement */ return null; } + + public String toString() { + return "[Task: name="+this.name+", version="+this.version+"]"; + } } diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index 4d61849..e13fada 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -36,6 +36,9 @@ public static void main(String[] args) { for ( String input : wdl.getInputs() ) { System.out.println("input: " + input); } + for ( CompositeTaskSubTask task : wdl.getTasks() ) { + System.out.println("task: " + task); + } } else { usage(); } diff --git a/wdl/WdlParser.java b/wdl/WdlParser.java index 80b5f46..00e9ae5 100644 --- a/wdl/WdlParser.java +++ b/wdl/WdlParser.java @@ -13,60 +13,59 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1 }, - { -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1 }, - { 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 31, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 15, 15, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, 39, -1, -1, -1 }, - { -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 21, -1, -1, 21, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10 }, - { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1 }, - { 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32 }, - { -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, 30, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, - { -1, -1, 26, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, 14, 11, -1 }, + { -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, 33, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1 }, + { -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1 }, + { -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 4, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 44, -1, -1, -1, -1, -1, -1, 44, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 19, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 43, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 18, 18, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 31, -1, 3, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_COMPOSITE_TASK(0, "composite_task"), - TERMINAL_IN(1, "in"), - TERMINAL_IDENTIFIER(2, "identifier"), - TERMINAL_LBRACE(3, "lbrace"), - TERMINAL_COLON(4, "colon"), - TERMINAL_STEP(5, "step"), - TERMINAL_FOR(6, "for"), - TERMINAL_STRING(7, "string"), - TERMINAL_LPAREN(8, "lparen"), - TERMINAL_LSQUARE(9, "lsquare"), - TERMINAL_COMMA(10, "comma"), - TERMINAL_DOT(11, "dot"), - TERMINAL_FILE(12, "file"), - TERMINAL_RPAREN(13, "rparen"), - TERMINAL_RBRACE(14, "rbrace"), - TERMINAL_INPUT(15, "input"), - TERMINAL_RSQUARE(16, "rsquare"), - TERMINAL_SEMI(17, "semi"), - TERMINAL_OUTPUT(18, "output"), - TERMINAL_NUMBER(19, "number"), - TERMINAL_ASSIGN(20, "assign"), - TERMINAL_AS(21, "as"); + TERMINAL_RPAREN(0, "rparen"), + TERMINAL_OUTPUT(1, "output"), + TERMINAL_FILE(2, "file"), + TERMINAL_LSQUARE(3, "lsquare"), + TERMINAL_AS(4, "as"), + TERMINAL_COMPOSITE_TASK(5, "composite_task"), + TERMINAL_STEP(6, "step"), + TERMINAL_IDENTIFIER(7, "identifier"), + TERMINAL_INPUT(8, "input"), + TERMINAL_STRING(9, "string"), + TERMINAL_RBRACE(10, "rbrace"), + TERMINAL_IN(11, "in"), + TERMINAL_SEMI(12, "semi"), + TERMINAL_NUMBER(13, "number"), + TERMINAL_RSQUARE(14, "rsquare"), + TERMINAL_COLON(15, "colon"), + TERMINAL_ASSIGN(16, "assign"), + TERMINAL_FOR(17, "for"), + TERMINAL_LPAREN(18, "lparen"), + TERMINAL_DOT(19, "dot"), + TERMINAL_COMMA(20, "comma"), + TERMINAL_LBRACE(21, "lbrace"); private final int id; private final String string; TerminalId(int id, String string) { @@ -103,234 +102,228 @@ this.rules = new HashMap(); ArrayList list; String rule; - this.nonterminal_rules.put("step_output_list", new ArrayList()); - this.nonterminal_rules.put("_gen11", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); + this.nonterminal_rules.put("_gen10", new ArrayList()); + this.nonterminal_rules.put("step", new ArrayList()); this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); - this.nonterminal_rules.put("composite_task", new ArrayList()); - this.nonterminal_rules.put("composite_task_entity", new ArrayList()); - this.nonterminal_rules.put("_gen1", new ArrayList()); - this.nonterminal_rules.put("step_attr", new ArrayList()); - this.nonterminal_rules.put("task_identifier", new ArrayList()); - this.nonterminal_rules.put("_gen4", new ArrayList()); - this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen9", new ArrayList()); this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("_gen3", new ArrayList()); - this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("variable", new ArrayList()); - this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("_gen7", new ArrayList()); this.nonterminal_rules.put("_gen2", new ArrayList()); - this.nonterminal_rules.put("wdl", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("composite_task_entity", new ArrayList()); this.nonterminal_rules.put("step_name", new ArrayList()); - this.nonterminal_rules.put("step", new ArrayList()); + this.nonterminal_rules.put("_gen3", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); this.nonterminal_rules.put("step_output", new ArrayList()); - this.nonterminal_rules.put("wdl_entity", new ArrayList()); - this.nonterminal_rules.put("_gen9", new ArrayList()); - this.nonterminal_rules.put("step_input_list", new ArrayList()); - this.nonterminal_rules.put("_gen10", new ArrayList()); + this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("step_input", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); this.nonterminal_rules.put("task_attr_value", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); this.nonterminal_rules.put("_gen8", new ArrayList()); - rule = "_gen11 := variable_member"; - this.nonterminal_rules.get("_gen11").add(rule); + this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("_gen7", new ArrayList()); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); this.rules.put(new Integer(0), rule); - rule = "_gen11 := ε"; - this.nonterminal_rules.get("_gen11").add(rule); + rule = "_gen7 := 'comma' step_input _gen7"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(1), rule); - rule = "_gen2 := step _gen2"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); this.rules.put(new Integer(2), rule); - rule = "step_output_list := 'output' 'colon' _gen9 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(3), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "composite_task_entity := composite_task"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(4), rule); - rule = "_gen8 := ε"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "_gen7 := ε"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(5), rule); - rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; - this.nonterminal_rules.get("step_input").add(rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(6), rule); - rule = "wdl := _gen0"; - this.nonterminal_rules.get("wdl").add(rule); + rule = "_gen5 := ε"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(7), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "_gen6 := ε"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(8), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(9), rule); - rule = "_gen3 := step_name"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + this.nonterminal_rules.get("task_attr").add(rule); this.rules.put(new Integer(10), rule); - rule = "_gen7 := ε"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(11), rule); - rule = "_gen3 := ε"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; + this.nonterminal_rules.get("step_output").add(rule); this.rules.put(new Integer(12), rule); - rule = "task_attr_value := 'number'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(13), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "_gen10 := variable_member"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(14), rule); - rule = "_gen1 := composite_task_entity _gen1"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(15), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(16), rule); - rule = "_gen8 := 'comma' step_input _gen8"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(17), rule); - rule = "variable_member := 'dot' 'identifier' -> $1"; - this.nonterminal_rules.get("variable_member").add(rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(18), rule); - rule = "_gen6 := ε"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "_gen4 := task_attrs"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(19), rule); - rule = "_gen9 := step_output _gen10"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "variable := 'identifier' _gen10 -> Variable( member=$1, name=$0 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(20), rule); - rule = "_gen4 := step_attr _gen4"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "_gen2 := step_name"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(21), rule); - rule = "wdl_entity := composite_task"; - this.nonterminal_rules.get("wdl_entity").add(rule); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(22), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(23), rule); - rule = "_gen7 := step_input _gen8"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; + this.nonterminal_rules.get("step").add(rule); this.rules.put(new Integer(24), rule); - rule = "_gen4 := ε"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "_gen8 := step_output _gen9"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(25), rule); - rule = "task_attr_value := 'identifier'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "task_identifier := 'identifier' _gen4 -> Task( attributes=$1, name=$0 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(26), rule); - rule = "_gen0 := wdl_entity _gen0"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); this.rules.put(new Integer(27), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; - this.nonterminal_rules.get("task_attr").add(rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(28), rule); - rule = "step_input_list := 'input' 'colon' _gen7 'semi' -> StepInputList( inputs=$2 )"; + rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(29), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); - this.rules.put(new Integer(30), rule); rule = "composite_task_entity := step"; this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(30), rule); + rule = "task_attr_value := 'identifier'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(31), rule); - rule = "step_name := 'as' 'identifier' -> $1"; - this.nonterminal_rules.get("step_name").add(rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(32), rule); - rule = "task_identifier := 'identifier' _gen5 -> Task( attributes=$1, name=$0 )"; - this.nonterminal_rules.get("task_identifier").add(rule); + rule = "_gen9 := 'comma' step_output _gen9"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(33), rule); - rule = "_gen10 := ε"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); this.rules.put(new Integer(34), rule); - rule = "_gen5 := task_attrs"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "_gen2 := ε"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(35), rule); - rule = "variable := 'identifier' _gen11 -> Variable( member=$1, name=$0 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(36), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen2 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; - this.nonterminal_rules.get("for_loop").add(rule); - this.rules.put(new Integer(37), rule); - rule = "_gen5 := ε"; + rule = "_gen5 := task_attr _gen5"; this.nonterminal_rules.get("_gen5").add(rule); + this.rules.put(new Integer(37), rule); + rule = "_gen6 := step_input _gen7"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(38), rule); - rule = "step_attr := step_output_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(39), rule); - rule = "task_attrs := 'lsquare' _gen6 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(40), rule); - rule = "_gen2 := ε"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); this.rules.put(new Integer(41), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen0 := wdl_entity _gen0"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(42), rule); - rule = "step := 'step' task_identifier _gen3 'lbrace' _gen4 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; - this.nonterminal_rules.get("step").add(rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(43), rule); - rule = "_gen10 := 'comma' step_output _gen10"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "_gen3 := step_attr _gen3"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(44), rule); - rule = "_gen6 := task_attr _gen6"; - this.nonterminal_rules.get("_gen6").add(rule); - this.rules.put(new Integer(45), rule); - this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.first.put("_gen11", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); - this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); + this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); - this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_STEP }); - this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); - this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); - this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.follow.put("_gen11", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("wdl", new TerminalId[] { }); - this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("wdl", new TerminalId[] { }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); } public TerminalMap getTerminalMap() { return new WdlTerminalMap(TerminalId.values()); @@ -350,66 +343,58 @@ private boolean isTerminal(TerminalId terminal) { return (0 <= terminal.id() && terminal.id() <= 21); } private boolean isNonTerminal(TerminalId terminal) { - return (22 <= terminal.id() && terminal.id() <= 51); + return (22 <= terminal.id() && terminal.id() <= 50); } private boolean isTerminal(int terminal) { return (0 <= terminal && terminal <= 21); } private boolean isNonTerminal(int terminal) { - return (22 <= terminal && terminal <= 51); + return (22 <= terminal && terminal <= 50); } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "step_output_list")); + ParseTree tree = new ParseTree( new NonTerminal(22, "wdl_entity")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") + "wdl_entity", + Arrays.asList(this.first.get("wdl_entity")), + this.nonterminal_rules.get("wdl_entity") )); } - if (rule == 3) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(3)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(3)); - tree.add(next); - subtree = this.parse__gen9(); + if (rule == 41) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(3)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_list")); + List terminals = Arrays.asList(this.first.get("wdl_entity")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", + "wdl_entity", current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(3) + Arrays.asList(this.first.get("wdl_entity")), + this.rules.get(41) )); } - private ParseTree parse__gen11() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen11")); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen10")); tree.setList(null); if ( current != null ) { - if (current.getId() == 10 || current.getId() == 17) { + if (current.getId() == 12 || current.getId() == 20) { return tree; } } if (current == null) { return tree; } - if (rule == 0) { + if (rule == 14) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_variable_member(); tree.add( subtree); @@ -417,256 +402,273 @@ private ParseTree parse__gen11() throws SyntaxError { } return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "task_attr")); + ParseTree tree = new ParseTree( new NonTerminal(24, "step")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") )); } - if (rule == 28) { + if (rule == 24) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(28)); + parameters.put("body", 4); + parameters.put("task", 1); + parameters.put("name", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(24)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(28)); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(24)); tree.add(next); - subtree = this.parse_task_attr_value(); + subtree = this.parse__gen3(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(24)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr")); + List terminals = Arrays.asList(this.first.get("step")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", + "step", current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(28) + Arrays.asList(this.first.get("step")), + this.rules.get(24) )); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "_gen6")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 16) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(25, "task_attr")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") + )); } - if (rule == 45) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); - tree.add( subtree); - subtree = this.parse__gen6(); + if (rule == 10) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(10)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(10)); + tree.add(next); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("task_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr", + current, + Arrays.asList(this.first.get("task_attr")), + this.rules.get(10) + )); } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "composite_task")); + ParseTree tree = new ParseTree( new NonTerminal(26, "step_input_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task", - Arrays.asList(this.first.get("composite_task")), - this.nonterminal_rules.get("composite_task") + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") )); } - if (rule == 16) { + if (rule == 29) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(16)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(16)); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(29)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(16)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(29)); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse__gen6(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(16)); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(29)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task")); + List terminals = Arrays.asList(this.first.get("step_input_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task", + "step_input_list", current, - Arrays.asList(this.first.get("composite_task")), - this.rules.get(16) + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(29) )); } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "composite_task_entity")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task_entity", - Arrays.asList(this.first.get("composite_task_entity")), - this.nonterminal_rules.get("composite_task_entity") - )); + ParseTree tree = new ParseTree( new NonTerminal(27, "_gen5")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 14) { + return tree; + } } - if (rule == 9) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); - tree.add( subtree); + if (current == null) { return tree; } - else if (rule == 31) { + if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task_entity", - current, - Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(31) - )); + return tree; } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen1")); - tree.setList("nlist"); + ParseTree tree = new ParseTree( new NonTerminal(28, "_gen9")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 15) { + if (rule == 33) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(33)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "step_attr")); + ParseTree tree = new ParseTree( new NonTerminal(29, "variable_member")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_attr", - Arrays.asList(this.first.get("step_attr")), - this.nonterminal_rules.get("step_attr") + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") )); } - if (rule == 39) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); - tree.add( subtree); - return tree; - } - else if (rule == 42) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); - tree.add( subtree); + if (rule == 22) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(22)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(22)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_attr")); + List terminals = Arrays.asList(this.first.get("variable_member")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_attr", + "variable_member", current, - Arrays.asList(this.first.get("step_attr")), - this.rules.get(42) + Arrays.asList(this.first.get("variable_member")), + this.rules.get(22) )); } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "task_identifier")); + ParseTree tree = new ParseTree( new NonTerminal(30, "_gen2")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 21) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 21) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_name(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_for_loop() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_identifier", - Arrays.asList(this.first.get("task_identifier")), - this.nonterminal_rules.get("task_identifier") + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") )); } - if (rule == 33) { + if (rule == 40) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(33)); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(40)); tree.add(next); - subtree = this.parse__gen5(); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(40)); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(40)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_identifier")); + List terminals = Arrays.asList(this.first.get("for_loop")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_identifier", + "for_loop", current, - Arrays.asList(this.first.get("task_identifier")), - this.rules.get(33) + Arrays.asList(this.first.get("for_loop")), + this.rules.get(40) )); } - private ParseTree parse__gen4() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 14) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 21) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); - tree.add( subtree); - subtree = this.parse__gen4(); - tree.add( subtree); - return tree; - } - return tree; - } private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; @@ -681,13 +683,13 @@ private ParseTree parse_task_attrs() throws SyntaxError { this.nonterminal_rules.get("task_attrs") )); } - if (rule == 40) { + if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(40)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(27)); tree.add(next); - subtree = this.parse__gen6(); + subtree = this.parse__gen5(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(40)); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(27)); tree.add(next); return tree; } @@ -696,593 +698,565 @@ private ParseTree parse_task_attrs() throws SyntaxError { "task_attrs", current, Arrays.asList(this.first.get("task_attrs")), - this.rules.get(40) + this.rules.get(27) )); } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "variable_member")); + ParseTree tree = new ParseTree( new NonTerminal(33, "composite_task_entity")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") + "composite_task_entity", + Arrays.asList(this.first.get("composite_task_entity")), + this.nonterminal_rules.get("composite_task_entity") )); } - if (rule == 18) { + if (rule == 4) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); + tree.add( subtree); + return tree; + } + else if (rule == 6) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_for_loop(); + tree.add( subtree); + return tree; + } + else if (rule == 30) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task_entity", + current, + Arrays.asList(this.first.get("composite_task_entity")), + this.rules.get(30) + )); + } + private ParseTree parse_step_name() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "step_name")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") + )); + } + if (rule == 34) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(18)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(34)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(18)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(34)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("variable_member")); + List terminals = Arrays.asList(this.first.get("step_name")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", + "step_name", current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(18) + Arrays.asList(this.first.get("step_name")), + this.rules.get(34) )); } private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "_gen3")); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "_gen3")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 10) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 44) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_attr(); + tree.add( subtree); + subtree = this.parse__gen3(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse__gen4() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "_gen4")); tree.setList(null); if ( current != null ) { - if (current.getId() == 3) { + if (current.getId() == 4) { return tree; } } if (current == null) { return tree; } - if (rule == 10) { + if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "for_loop")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "for_loop", - Arrays.asList(this.first.get("for_loop")), - this.nonterminal_rules.get("for_loop") + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") )); } - if (rule == 37) { + if (rule == 12) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(37)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(37)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(37)); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(12)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(37)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(12)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(37)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(12)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(37)); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(12)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(37)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(12)); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse_variable(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(37)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("for_loop")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "for_loop", + "step_output", current, - Arrays.asList(this.first.get("for_loop")), - this.rules.get(37) + Arrays.asList(this.first.get("step_output")), + this.rules.get(12) )); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "variable")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "task_identifier")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable", - Arrays.asList(this.first.get("variable")), - this.nonterminal_rules.get("variable") + "task_identifier", + Arrays.asList(this.first.get("task_identifier")), + this.nonterminal_rules.get("task_identifier") )); } - if (rule == 36) { + if (rule == 26) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); + parameters.put("attributes", 1); parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(36)); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(26)); tree.add(next); - subtree = this.parse__gen11(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable")); + List terminals = Arrays.asList(this.first.get("task_identifier")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable", + "task_identifier", current, - Arrays.asList(this.first.get("variable")), - this.rules.get(36) + Arrays.asList(this.first.get("task_identifier")), + this.rules.get(26) )); } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step_input")); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "step_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") )); } - if (rule == 6) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(6)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(6)); - tree.add(next); - subtree = this.parse_variable(); + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input_list(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); + else if (rule == 43) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", + "step_attr", current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(6) + Arrays.asList(this.first.get("step_attr")), + this.rules.get(43) )); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen6")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 17) { + if (current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 24) { + if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen8(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen2() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen2")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 14) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); - subtree = this.parse__gen2(); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "wdl")); + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "step_input")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") + )); } - if (rule == 7) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); + if (rule == 2) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(2)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(2)); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("wdl")); + List terminals = Arrays.asList(this.first.get("step_input")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl", + "step_input", current, - Arrays.asList(this.first.get("wdl")), - this.rules.get(7) + Arrays.asList(this.first.get("step_input")), + this.rules.get(2) )); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "_gen0")); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "_gen1")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 10) { return tree; } } if (current == null) { return tree; } - if (rule == 27) { + if (rule == 18) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "step_name")); - tree.setList(null); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen0")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == -1) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_name", - Arrays.asList(this.first.get("step_name")), - this.nonterminal_rules.get("step_name") - )); + return tree; } - if (rule == 32) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(32)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(32)); - tree.add(next); + if (rule == 42) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_wdl_entity(); + tree.add( subtree); + subtree = this.parse__gen0(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_name")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_name", - current, - Arrays.asList(this.first.get("step_name")), - this.rules.get(32) - )); + return tree; } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "step")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "step_output_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step", - Arrays.asList(this.first.get("step")), - this.nonterminal_rules.get("step") + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") )); } - if (rule == 43) { + if (rule == 15) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 4); - parameters.put("task", 1); - parameters.put("name", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(43)); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(15)); tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(15)); tree.add(next); - subtree = this.parse__gen4(); + subtree = this.parse__gen8(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(15)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step")); + List terminals = Arrays.asList(this.first.get("step_output_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step", + "step_output_list", current, - Arrays.asList(this.first.get("step")), - this.rules.get(43) + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(15) )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "step_output")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 23) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(23)); + if (rule == 3) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(3)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(23)); + return tree; + } + else if (rule == 17) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(17)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(23)); + return tree; + } + else if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(31)); tree.add(next); - subtree = this.parse_variable(); - tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + List terminals = Arrays.asList(this.first.get("task_attr_value")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "task_attr_value", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(23) + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(31) )); } - private ParseTree parse_wdl_entity() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "wdl_entity")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "variable")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "wdl_entity", - Arrays.asList(this.first.get("wdl_entity")), - this.nonterminal_rules.get("wdl_entity") + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") )); } - if (rule == 22) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + if (rule == 20) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(20)); + tree.add(next); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("wdl_entity")); + List terminals = Arrays.asList(this.first.get("variable")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl_entity", + "variable", current, - Arrays.asList(this.first.get("wdl_entity")), - this.rules.get(22) + Arrays.asList(this.first.get("variable")), + this.rules.get(20) )); } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "_gen9")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen8")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 17) { + if (current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 20) { + if (rule == 25) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen10(); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "step_input_list")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "wdl")); tree.setList(null); if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") - )); + return tree; } - if (rule == 29) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(29)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(29)); - tree.add(next); - subtree = this.parse__gen7(); + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(29)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); + List terminals = Arrays.asList(this.first.get("wdl")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", + "wdl", current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(29) + Arrays.asList(this.first.get("wdl")), + this.rules.get(0) )); } - private ParseTree parse__gen10() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "_gen10")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 17) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 44) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen10", this.rules.get(44)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen10(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "task_attr_value")); + ParseTree tree = new ParseTree( new NonTerminal(49, "composite_task")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr_value", - Arrays.asList(this.first.get("task_attr_value")), - this.nonterminal_rules.get("task_attr_value") + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") )); } - if (rule == 13) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(13)); + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(28)); tree.add(next); - return tree; - } - else if (rule == 14) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(14)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(28)); tree.add(next); - return tree; - } - else if (rule == 26) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(26)); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(28)); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(28)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr_value")); + List terminals = Arrays.asList(this.first.get("composite_task")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr_value", + "composite_task", current, - Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(26) + Arrays.asList(this.first.get("composite_task")), + this.rules.get(28) )); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen5")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 21) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 35) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen8() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(51, "_gen8")); + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen7")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 17) { + if (current.getId() == 12) { return tree; } } if (current == null) { return tree; } - if (rule == 17) { + if (rule == 1) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen8", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(1)); tree.add(next); tree.setListSeparator(next); subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } diff --git a/wdl/wdl.zgr b/wdl/wdl.zgr index f3e0ea2..a58793d 100644 --- a/wdl/wdl.zgr +++ b/wdl/wdl.zgr @@ -5,8 +5,8 @@ "wdl := list(wdl_entity)", "wdl_entity := composite_task", "composite_task := 'composite_task' + 'identifier' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> CompositeTask( name=$1, body=$3 )", - "composite_task_entity := step | for_loop", - "for_loop := 'for' + 'lparen' + 'identifier' + 'in' + 'identifier' + 'rparen' + 'lbrace' + list(step) + 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )", + "composite_task_entity := step | for_loop | composite_task", + "for_loop := 'for' + 'lparen' + 'identifier' + 'in' + 'identifier' + 'rparen' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )", "step := 'step' + task_identifier + optional(step_name) + 'lbrace' + list(step_attr) + 'rbrace' -> Step( task=$1, name=$2, body=$4 )", "task_identifier := 'identifier' + optional(task_attrs) -> Task(name=$0, attributes=$1)", "task_attrs := 'lsquare' + list(task_attr) + 'rsquare' -> $1", From f79ea99a778146a56505e983fb3b559a53a66fb0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 20 Aug 2012 09:41:58 -0300 Subject: [PATCH 038/140] Update wdl/README.md --- wdl/README.md | 298 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 246 insertions(+), 52 deletions(-) diff --git a/wdl/README.md b/wdl/README.md index 844dc35..155891a 100644 --- a/wdl/README.md +++ b/wdl/README.md @@ -1,7 +1,7 @@ Usage ===== -There are two example .wdl files in this directory that parse: +There are two example .wdl files in the examples/ directory: * MutSig.wdl * CopyNumberQC.wdl @@ -9,69 +9,206 @@ There are two example .wdl files in this directory that parse: From Java code, the main interface is the CompositeTask, which can be used in this example to acquire the name of each task: ```java -CompositeTask wdl = new CompositeTask(new File(args[0])); -Map steps = wdl.getSteps(); -for ( Map.Entry entry : steps.entrySet() ) { - System.out.println("Step: " + entry.getKey()); +CompositeTask ct = new CompositeTask(new File(args[0])); +for ( CompositeTaskNode entry : ct.getNodes() ) { + System.out.println("Node: " + entry); } ``` To extract parse tree, and abstract syntax tree information from the command line: +First compile the sources: ``` $ javac *.java -$ cat simple.wdl -composite_task x {step y[version=0] {}} -$ java WdlMain simple.wdl parsetree -(wdl: - (_gen0: - (wdl_entity: - (composite_task: - composite_task, - identifier, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen5: - (task_attrs: - lsquare, - (_gen6: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen6: ) - ), - rsquare +$ cat examples/0.zgr +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=s; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=y; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} +``` + +Get the abstract syntax tree: + +``` +$ java WdlMain examples/0.wdl ast +(CompositeTask: + body=[ + (Step: + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (ForLoop: + body=[ + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier ) ) - ), - (_gen3: ), - lbrace, - (_gen4: ), - rbrace + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier ), - (_gen1: ) + name=None ), - rbrace - ) + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + item=identifier, + collection=identifier ), - (_gen0: ) - ) -) -$ java WdlMain simple.wdl ast -(CompositeTask: - body=[ (Step: - body=[], + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], task=(Task: attributes=[ (TaskAttribute: @@ -86,6 +223,63 @@ $ java WdlMain simple.wdl ast ], name=identifier ) -$ java WdlMain simple.wdl nodes -Step: y +``` + +Get a view of the graph + +``` +$ java WdlMain examples/0.wdl graph +[Step: name=dtask] +[Step: name=atask] +[CompositeTaskForScope: collection=foo, var=item, # nodes=2] +[Edge + from=[Output node=[Step: name=atask], path="foo.txt"], + to=[Input node=[Step: name=dtask], param=p0], + var=x +] +[Edge + from=[Output node=[Step: name=atask], path="foo.txt"], + to=[Input node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], param=null], + var=x +] +[Edge + from=[Output node=[Step: name=atask], path="foo.txt"], + to=[Input node=[Step: name=btask], param=p0], + var=x +] +[Edge + from=[Output node=[Step: name=atask], path="foo.txt"], + to=[Input node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], param=null], + var=x +] +[Edge + from=[Output node=[Step: name=atask], path="foo.txt"], + to=[Input node=[Step: name=ctask], param=p0], + var=x +] +[Edge + from=[Output node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], path="bar.txt"], + to=[Input node=[Step: name=dtask], param=p1], + var=y +] +[Edge + from=[Output node=[Step: name=btask], path="bar.txt"], + to=[Input node=[Step: name=dtask], param=p1], + var=y +] +[Edge + from=[Output node=[Step: name=btask], path="bar.txt"], + to=[Input node=[Step: name=ctask], param=p1], + var=y +] +[Edge + from=[Output node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], path="quux.txt"], + to=[Input node=[Step: name=dtask], param=p2], + var=z +] +[Edge + from=[Output node=[Step: name=ctask], path="quux.txt"], + to=[Input node=[Step: name=dtask], param=p2], + var=z +] ``` From 1578c29a6e5772f1e6bd7e7b8e0c957d7f7a2c75 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 20 Aug 2012 14:44:25 -0300 Subject: [PATCH 039/140] Update wdl/README.md --- wdl/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wdl/README.md b/wdl/README.md index 155891a..dfb8979 100644 --- a/wdl/README.md +++ b/wdl/README.md @@ -15,12 +15,14 @@ for ( CompositeTaskNode entry : ct.getNodes() ) { } ``` -To extract parse tree, and abstract syntax tree information from the command line: - -First compile the sources: +Compiling is relatively straightforward: ``` $ javac *.java -$ cat examples/0.zgr +``` + +The data file we'll use is: + +``` composite_task foo { step atask[version=0] { From 39dd7fb97ba96e1d8cdd0906fe5c23c06ec1bc92 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 20 Aug 2012 16:57:49 -0400 Subject: [PATCH 040/140] two more example files --- wdl/examples/3.wdl | 28 ++++++++++++++++++++++++++++ wdl/examples/4.wdl | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 wdl/examples/3.wdl create mode 100644 wdl/examples/4.wdl diff --git a/wdl/examples/3.wdl b/wdl/examples/3.wdl new file mode 100644 index 0000000..97ea303 --- /dev/null +++ b/wdl/examples/3.wdl @@ -0,0 +1,28 @@ +composite_task foo { + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha; + output: File("baz.txt") as gamma; + } + + step btask[version=0] { + input: p0=beta; + output: File("quux.txt") as epsilon; + } + } + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + +} diff --git a/wdl/examples/4.wdl b/wdl/examples/4.wdl new file mode 100644 index 0000000..cad77ce --- /dev/null +++ b/wdl/examples/4.wdl @@ -0,0 +1,30 @@ +composite_task foo { + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha; + output: File("baz.txt") as gamma; + } + } + + for ( item in items ) { + step btask[version=0] { + input: p0=beta; + output: File("quux.txt") as epsilon; + } + } + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + +} From 33414747191e94e2108c6eb9cef25ba0b9527fd5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 21 Aug 2012 08:36:36 -0400 Subject: [PATCH 041/140] new example file --- wdl/examples/5.wdl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 wdl/examples/5.wdl diff --git a/wdl/examples/5.wdl b/wdl/examples/5.wdl new file mode 100644 index 0000000..f1d7118 --- /dev/null +++ b/wdl/examples/5.wdl @@ -0,0 +1,33 @@ +composite_task foo { + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha; + output: File("baz.txt") as gamma; + } + } + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + step batman[version=0] {} + step robin[version=0] {} + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + + for ( item in items ) { + step btask[version=0] { + input: p0=beta; + output: File("quux.txt") as epsilon; + } + } + +} From 3edae1d605bf2b152a8f1c3f80d69986bb6ab661 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 22 Aug 2012 17:20:35 -0400 Subject: [PATCH 042/140] wip --- wdl/CompositeTasStepInput.java | 38 +++ wdl/CompositeTask.java | 313 +++------------------ wdl/CompositeTaskBaseScope.java | 19 -- wdl/CompositeTaskEdge.java | 34 --- ...TaskForScope.java => CompositeTaskForLoop.java} | 11 +- wdl/CompositeTaskInput.java | 34 --- wdl/CompositeTaskOutput.java | 35 --- wdl/CompositeTaskStep.java | 15 +- wdl/CompositeTaskStepOutput.java | 43 +++ wdl/CompositeTaskVariable.java | 42 +++ wdl/examples/0.wdl | 2 +- wdl/examples/1.wdl | 2 +- wdl/examples/2.wdl | 30 ++ wdl/examples/6.wdl | 12 + 14 files changed, 213 insertions(+), 417 deletions(-) create mode 100644 wdl/CompositeTasStepInput.java delete mode 100644 wdl/CompositeTaskBaseScope.java rename wdl/{CompositeTaskForScope.java => CompositeTaskForLoop.java} (63%) delete mode 100644 wdl/CompositeTaskInput.java delete mode 100644 wdl/CompositeTaskOutput.java create mode 100644 wdl/CompositeTaskStepOutput.java create mode 100644 wdl/CompositeTaskVariable.java create mode 100644 wdl/examples/2.wdl create mode 100644 wdl/examples/6.wdl diff --git a/wdl/CompositeTasStepInput.java b/wdl/CompositeTasStepInput.java new file mode 100644 index 0000000..d2468f4 --- /dev/null +++ b/wdl/CompositeTasStepInput.java @@ -0,0 +1,38 @@ +import java.util.Set; + +class CompositeTaskStepInput { + private String parameter; + private CompositeTaskVariable variable; + + public CompositeTaskStepInput(String parameter, CompositeTaskVariable variable) { + this.parameter = parameter; + this.variable = variable; + } + + public CompositeTaskStepInput(Ast ast) { + } + + public Ast getAst() { + return null; + } + + public String getParameter() { + return this.parameter; + } + + public CompositeTaskVariable getVariable() { + return this.variable; + } + + public int hashCode() { + return 0; + } + + public boolean equals(CompositeTaskStepInput other) { + return false; + } + + public String toString() { + return "[StepInput: parameter=" + this.parameter + "]"; + } +} diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 7d04903..1aa3660 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -12,8 +12,6 @@ private ParseTree parse_tree; private Ast ast; private WdlSyntaxErrorFormatter error_formatter; - private Set nodes; - private Set edges; private Set inputs; private String name; @@ -49,93 +47,40 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { * d) Two outputs have the same name */ - AstList steps = (AstList) composite_task.getAttribute("body"); + AstList ctNodes = (AstList) composite_task.getAttribute("body"); + Set nodes = new HashSet(); - for ( AstNode step : steps ) { - CompositeTask.this.nodes.add( verify((Ast) step) ); + for ( AstNode ctNode : ctNodes ) { + Ast node = (Ast) ctNode; + if (node.getName().equals("Step")) { + nodes.add(new CompositeTaskStep(ast)); + } else if (node.getName().equals("ForLoop")) { + nodes.add(new CompositeTaskForLoop(ast)); + } else if (node.getName().equals("CompositeTask")) { + nodes.add(new CompositeTaskStep(ast)); + } else { + throw new SyntaxError("TODO"); + } } - /* outputs: Map of String variable_name -> Set which represents a set of - * entities that write an output to that variable. e.g. output: File("foo.txt") as bar would - * add an entry to outputs at key 'bar'. No two outputs should write to the same variable. - * - * inputs: Map of String variable_name -> Set which represents the set of - * nodes that need variable_name as a prerequisite. Note that this also includes Scope nodes - * like 'for' or 'composite_task' nodes. Also note that get_node_inputs() actually generates - * scope inputs based on the union of all of the inputs of its sub-nodes, which isn't terribly - * useful because a lot of those could be satisfied internally. For example: - * - * composite_task test { - * step foo[version=0] { - * output: File("foo.txt") as bar - * } + /* Graph definition: + * + * Verticies: + * scope, step, variable * - * step baz[version=0] { - * input: x=bar, y=var - * } - * } + * Edges: + * scope -> step : Step is dependent on scope completing + * scope (for) -> variable : Variable is the loop variable (not collection). + * Each for loop contains exactly one of these edges + * scope -> scope : Doesn't exist. + * variable -> scope (for) : Variable is the loop collection + * variable -> step : Step needs variable as an input + * variable -> variable : Doesn't exist. + * step -> variable : Variable is an output of step + * step -> scope : Doesn't exist. + * step -> step : Doesn't exist. * - * the composite task will have inputs bar and var (on top of the inputs from step foo and baz). - * However, 'bar' is already satisfied by step foo so the composite task really only needs 'foo' */ - Map> outputs = get_node_outputs(CompositeTask.this); - Map> inputs = get_node_inputs(CompositeTask.this); - - /* Map outputs -> inputs, creating the edges in the graph */ - for ( Map.Entry> entry : outputs.entrySet() ) { - String variable = entry.getKey(); - Set output_set = entry.getValue(); - for ( CompositeTaskOutput output: output_set ) { - if ( output.getNode() == CompositeTask.this ) { - continue; - } - if ( inputs.get(variable) != null ) { - for ( CompositeTaskInput input : inputs.get(variable) ) { - if ( input.getNode() == CompositeTask.this ) { - continue; - } - if ( input.getNode() == output.getNode() ) { - continue; - } - if ( output.getNode() instanceof CompositeTaskScope && - in_scope((CompositeTaskScope) output.getNode(), input.getNode()) ) { - continue; - } - if ( input.getNode() instanceof CompositeTaskScope && - in_scope((CompositeTaskScope) input.getNode(), output.getNode()) ) { - continue; - } - CompositeTaskEdge edge = new CompositeTaskEdge(output, input, variable); - CompositeTask.this.edges.add(edge); - } - } - } - } - - for ( Map.Entry> entry : inputs.entrySet() ) { - Set in_set = entry.getValue(); - String variable = entry.getKey(); - - Iterator iter = in_set.iterator(); - while (iter.hasNext()) { - CompositeTaskInput in = iter.next(); - if ( in.getNode() instanceof CompositeTaskScope ) { - if ( outputs_variable(in.getNode(), variable) ) { - iter.remove(); - } - } - } - } - - for ( Map.Entry> entry : inputs.entrySet() ) { - String variable = entry.getKey(); - Set ins = entry.getValue(); - for ( CompositeTaskInput input : ins ) { - if ( input.getNode() == CompositeTask.this ) { - CompositeTask.this.inputs.add(variable); - } - } - } return composite_task; } @@ -151,25 +96,6 @@ private boolean in_scope(CompositeTaskScope scope, CompositeTaskNode node) { return answer; } - private boolean outputs_variable(CompositeTaskNode node, String variable) { - if (node instanceof CompositeTaskScope) { - CompositeTaskScope scope = (CompositeTaskScope) node; - boolean answer = false; - for ( CompositeTaskNode scope_node : scope.getNodes() ) { - answer |= outputs_variable(scope_node, variable); - } - return answer; - } else if (node instanceof CompositeTaskStep) { - CompositeTaskStep step = (CompositeTaskStep) node; - for ( CompositeTaskEdge edge : CompositeTask.this.edges ) { - if ( edge.getVariable().equals(variable) && edge.getStart().getNode() == step) { - return true; - } - } - } - return false; - } - private String variable_to_string(Ast variable) { String name; Terminal asName = (Terminal) variable.getAttribute("name"); @@ -182,98 +108,6 @@ private String variable_to_string(Ast variable) { return name; } - private Map> get_node_inputs(CompositeTaskNode node) throws SyntaxError { - Map> inputs = new HashMap>(); - if ( node instanceof CompositeTaskStep ) { - AstList node_body = (AstList) node.getAst().getAttribute("body"); - for ( AstNode elem : node_body ) { - if ( elem instanceof Ast && ((Ast) elem).getName().equals("StepInputList") ) { - for ( AstNode input_node : (AstList) ((Ast) elem).getAttribute("inputs") ) { - Ast input = (Ast) input_node; - if ( input.getName().equals("StepInput") ) { - String parameter = ((Terminal) input.getAttribute("parameter")).getSourceString(); - String variable = variable_to_string((Ast) input.getAttribute("value")); - if ( !inputs.containsKey(variable) ) { - inputs.put(variable, new HashSet()); - } - inputs.get(variable).add( new CompositeTaskInput(node, parameter) ); - } - } - } - } - } else if ( node instanceof CompositeTaskScope ) { - /* TODO: just change the behavior of this loop to include Scopes in the */ - for ( CompositeTaskNode sub_node : ((CompositeTaskScope) node).getNodes() ) { - for ( Map.Entry> input : get_node_inputs(sub_node).entrySet() ) { - String variable = input.getKey(); - Set in = input.getValue(); - - if ( !inputs.containsKey(variable) ) { - inputs.put(variable, new HashSet()); - } - - inputs.get(variable).addAll(in); - inputs.get(variable).add(new CompositeTaskInput(node)); - } - } - - if ( node instanceof CompositeTaskForScope ) { - String collection = ((CompositeTaskForScope) node).getCollectionName(); - if ( !inputs.containsKey(collection) ) { - inputs.put(collection, new HashSet()); - } - inputs.get(collection).add(new CompositeTaskInput(node)); - } - } - return inputs; - } - - private Map> get_node_outputs(CompositeTaskNode node) throws SyntaxError { - Map> outputs = new HashMap>(); - if ( node instanceof CompositeTaskStep ) { - AstList node_body = (AstList) node.getAst().getAttribute("body"); - for ( AstNode elem : node_body ) { - if ( elem instanceof Ast && ((Ast) elem).getName().equals("StepOutputList") ) { - for ( AstNode output_node : (AstList) ((Ast) elem).getAttribute("outputs") ) { - Ast output = (Ast) output_node; - if ( output.getName().equals("StepFileOutput") ) { - String file_path = ((Terminal) output.getAttribute("file")).getSourceString(); - String variable = variable_to_string((Ast) output.getAttribute("as")); - if ( !outputs.containsKey(variable) ) { - outputs.put(variable, new HashSet()); - } - outputs.get(variable).add( new CompositeTaskOutput(node, "File", file_path) ); - } - } - } - } - } else if ( node instanceof CompositeTaskScope ) { - Map scope_outputs = new HashMap(); - for ( CompositeTaskNode sub_node : ((CompositeTaskScope) node).getNodes() ) { - for ( Map.Entry> output : get_node_outputs(sub_node).entrySet() ) { - String variable = output.getKey(); - Set out = output.getValue(); - if ( !outputs.containsKey(variable) ) { - outputs.put(variable, new HashSet()); - } - - outputs.get(variable).addAll(out); - - for ( CompositeTaskOutput o : out ) { - if ( !scope_outputs.containsKey(variable) ) { - scope_outputs.put(variable, new CompositeTaskOutput(node, o.getType(), o.getPath())); - } - } - } - } - - for ( Map.Entry entry : scope_outputs.entrySet() ) { - outputs.get(entry.getKey()).add(entry.getValue()); - } - } - return outputs; - } - private CompositeTaskNode verify(Ast ast) throws SyntaxError { if ( ast.getName().equals("Step") ) { return verify_step(ast); @@ -286,7 +120,7 @@ private CompositeTaskNode verify(Ast ast) throws SyntaxError { } } - private CompositeTaskNode verify_step(Ast step) throws SyntaxError { + private CompositeTaskStep verify_step(Ast step) throws SyntaxError { Ast task = (Ast) step.getAttribute("task"); Terminal task_name = getTaskName(task); Terminal task_version = getTaskVersion(task); @@ -307,10 +141,10 @@ private CompositeTaskNode verify_step(Ast step) throws SyntaxError { ctStepName = task_name.getSourceString(); } - return new CompositeTaskStep(step, ctStepName, ctSubTask); + return new CompositeTaskStep(ctStepName, ctSubTask); } - private CompositeTaskNode verify_for(Ast for_node_ast) throws SyntaxError { + private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { Set nodes = new HashSet(); for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { @@ -320,17 +154,17 @@ private CompositeTaskNode verify_for(Ast for_node_ast) throws SyntaxError { String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); - return new CompositeTaskForScope(for_node_ast, collection, item, nodes); + return new CompositeTaskForLoop(collection, item, nodes); } - private CompositeTaskNode verify_composite_task(Ast ast) throws SyntaxError { + private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { Set nodes = new HashSet(); for ( AstNode sub : (AstList) ast.getAttribute("body") ) { nodes.add( verify((Ast) sub) ); } - return new CompositeTaskBaseScope(ast, nodes); + return new CompositeTask(nodes); } private Terminal getTaskName(Ast task) { @@ -356,18 +190,8 @@ private Terminal getTaskVersion(Ast task) { /** Constructors **/ - CompositeTask(String name, Set nodes, Set edges, Set inputs) { - this.name = name; - this.nodes = nodes; - this.edges = edges; - this.inputs = inputs; - } - - CompositeTask(String name) { + CompositeTask(String name, Set nodes) { this.name = name; - this.nodes = new HashSet(); - this.edges = new HashSet(); - this.inputs = new HashSet(); } CompositeTask(SourceCode source_code) throws SyntaxError { @@ -377,9 +201,6 @@ private Terminal getTaskVersion(Ast task) { this.parse_tree = (ParseTree) node; AstList ast_list = (AstList) node.toAst(); CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); - this.nodes = new HashSet(); - this.edges = new HashSet(); - this.inputs = new HashSet(); this.ast = verifier.verify(ast_list); } @@ -405,88 +226,26 @@ public String getName() { return this.nodes; } - public Set getEdges() { - return this.edges; - } - public CompositeTaskStep getStep(String name) { - for ( CompositeTaskNode node : this.nodes ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - if ( step.getName().equals(name) ) { - return step; - } - } - } return null; } - public CompositeTaskOutput getOutput(String name) { - for ( CompositeTaskEdge edge : this.edges ) { - if ( edge.getVariable().equals(name) ) { - return edge.getStart(); - } - } - return null; - } - public Set getTasks() { - Set tasks = new HashSet(); - for (CompositeTaskNode node : this.nodes) { - if ( node instanceof CompositeTaskStep ) { - tasks.add( ((CompositeTaskStep) node).getTask() ); - } else if ( node instanceof CompositeTaskScope ) { - tasks.addAll( getTasks((CompositeTaskScope) node)); - } - } - return tasks; + return null; } private Set getTasks(CompositeTaskScope scope) { - Set tasks = new HashSet(); - for (CompositeTaskNode node : scope.getNodes()) { - if ( node instanceof CompositeTaskStep ) { - tasks.add( ((CompositeTaskStep) node).getTask() ); - } else if ( node instanceof CompositeTaskScope ) { - tasks.addAll( getTasks((CompositeTaskScope) node)); - } - } return tasks; } - public Set getInputs() { - // Per task: - // 1) get input variables for task - // 2) remove 'parameter' value for all edges with to=task - // Named inputs - // add for loop collection values - return this.inputs; - } - - public Map> getDependencyGraph() { - return null; - } - public Ast getAst() { return this.ast; } - public void setNodes(Set nodes) { - this.nodes = nodes; - } - - public void setEdges(Set edges) { - this.edges = edges; - } - public void setName(String name) { this.name = name; } - public void addEdge(CompositeTaskEdge edge) { - this.edges.add(edge); - } - public void addNode(CompositeTaskNode node) { this.nodes.add(node); } diff --git a/wdl/CompositeTaskBaseScope.java b/wdl/CompositeTaskBaseScope.java deleted file mode 100644 index 5729b0c..0000000 --- a/wdl/CompositeTaskBaseScope.java +++ /dev/null @@ -1,19 +0,0 @@ -import java.util.Set; - -class CompositeTaskBaseScope implements CompositeTaskScope { - private Set nodes; - private Ast ast; - - CompositeTaskBaseScope(Ast ast, Set nodes) { - this.ast = ast; - this.nodes = nodes; - } - - public Set getNodes() { - return this.nodes; - } - - public Ast getAst() { - return this.ast; - } -} diff --git a/wdl/CompositeTaskEdge.java b/wdl/CompositeTaskEdge.java index 9b46a13..ec34f07 100644 --- a/wdl/CompositeTaskEdge.java +++ b/wdl/CompositeTaskEdge.java @@ -1,36 +1,2 @@ class CompositeTaskEdge { - private CompositeTaskOutput start; - private CompositeTaskInput end; - private String variable; - - public CompositeTaskEdge(CompositeTaskOutput start, CompositeTaskInput end, String variable) { - this.start = start; - this.end = end; - this.variable = variable; - } - - public CompositeTaskOutput getStart() { - return this.start; - } - - public CompositeTaskInput getEnd() { - return this.end; - } - - public String getVariable() { - return this.variable; - } - - /* TODO: How will these methods be implemented? */ - public int hashCode() { - return 0; - } - - public boolean equals(CompositeTaskEdge other) { - return false; - } - - public String toString() { - return "[Edge\n from="+this.start+",\n to="+this.end+",\n var="+this.variable+"\n]"; - } } diff --git a/wdl/CompositeTaskForScope.java b/wdl/CompositeTaskForLoop.java similarity index 63% rename from wdl/CompositeTaskForScope.java rename to wdl/CompositeTaskForLoop.java index 30691fa..e2e0a44 100644 --- a/wdl/CompositeTaskForScope.java +++ b/wdl/CompositeTaskForLoop.java @@ -1,23 +1,16 @@ import java.util.Set; -class CompositeTaskForScope implements CompositeTaskScope { +class CompositeTaskForLoop implements CompositeTaskScope { private String collection; private String var; private Set nodes; - private Ast ast; - public CompositeTaskForScope(String collection, String var, Set nodes) { - this.ast = null; + public CompositeTaskForLoop(String collection, String var, Set nodes) { this.collection = collection; this.var = var; this.nodes = nodes; } - public CompositeTaskForScope(Ast ast, String collection, String var, Set nodes) { - this(collection, var, nodes); - this.ast = ast; - } - public Ast getAst() { return this.ast; } diff --git a/wdl/CompositeTaskInput.java b/wdl/CompositeTaskInput.java deleted file mode 100644 index 043f51f..0000000 --- a/wdl/CompositeTaskInput.java +++ /dev/null @@ -1,34 +0,0 @@ -class CompositeTaskInput { - private CompositeTaskNode node; - private String parameter; - - public CompositeTaskInput(CompositeTaskNode node) { - this.node = node; - this.parameter = null; - } - - public CompositeTaskInput(CompositeTaskNode node, String parameter) { - this(node); - this.parameter = parameter; - } - - public CompositeTaskNode getNode() { - return this.node; - } - - public String getParameter() { - return this.parameter; - } - - public int hashCode() { - return 0; - } - - public boolean equals(CompositeTaskInput other) { - return false; - } - - public String toString() { - return "[Input node="+this.node+", param="+this.parameter+"]"; - } -} diff --git a/wdl/CompositeTaskOutput.java b/wdl/CompositeTaskOutput.java deleted file mode 100644 index b939238..0000000 --- a/wdl/CompositeTaskOutput.java +++ /dev/null @@ -1,35 +0,0 @@ -class CompositeTaskOutput { - private CompositeTaskNode node; - private String type; - private String path; - - public CompositeTaskOutput(CompositeTaskNode node, String type, String path) { - this.node = node; - this.type = type; - this.path = path; - } - - public CompositeTaskNode getNode() { - return this.node; - } - - public String getType() { - return this.type; - } - - public String getPath() { - return this.path; - } - - public int hashCode() { - return 0; - } - - public boolean equals(CompositeTaskOutput other) { - return false; - } - - public String toString() { - return "[Output node="+this.node+", path="+this.path+"]"; - } -} diff --git a/wdl/CompositeTaskStep.java b/wdl/CompositeTaskStep.java index aae2735..2a6c0fc 100644 --- a/wdl/CompositeTaskStep.java +++ b/wdl/CompositeTaskStep.java @@ -1,23 +1,25 @@ -import java.util.Collection; +import java.util.Set; class CompositeTaskStep implements CompositeTaskNode { private CompositeTaskSubTask task; private String name; - private Ast ast; + private Set inputs; + private Set outputs; - public CompositeTaskStep(String name, CompositeTaskSubTask task) { - this.ast = null; + public CompositeTaskStep(String name, CompositeTaskSubTask task, Set inputs, Set outputs) { this.task = task; this.name = name; + this.inputs = inputs; + this.outputs = outputs; } - public CompositeTaskStep(Ast ast, String name, CompositeTaskSubTask task) { + public CompositeTaskStep(Ast ast) { this(name, task); this.ast = ast; } public Ast getAst() { - return this.ast; + return null; } public String getName() { @@ -28,7 +30,6 @@ public CompositeTaskSubTask getTask() { return this.task; } - /* TODO: Are steps only unique by name? */ public int hashCode() { return 0; } diff --git a/wdl/CompositeTaskStepOutput.java b/wdl/CompositeTaskStepOutput.java new file mode 100644 index 0000000..f608138 --- /dev/null +++ b/wdl/CompositeTaskStepOutput.java @@ -0,0 +1,43 @@ +import java.util.Set; + +class CompositeTaskStepOutput { + private String type; + private String path; + private CompositeTaskVariable variable; + + public CompositeTaskStepOutput(String type, String path, CompositeTaskVariable variable) { + this.parameter = parameter; + this.variable = variable; + } + + public CompositeTaskStepOutput(Ast ast) { + } + + public Ast getAst() { + return null; + } + + public String getPath() { + return this.path; + } + + public String getType() { + return this.type; + } + + public CompositeTaskVariable getVariable() { + return this.variable; + } + + public int hashCode() { + return 0; + } + + public boolean equals(CompositeTaskStepOutput other) { + return false; + } + + public String toString() { + return "[StepOutput: name=" + this.name + "]"; + } +} diff --git a/wdl/CompositeTaskVariable.java b/wdl/CompositeTaskVariable.java new file mode 100644 index 0000000..2acfa08 --- /dev/null +++ b/wdl/CompositeTaskVariable.java @@ -0,0 +1,42 @@ +import java.util.Set; + +class CompositeTaskVariable { + private String name; + private String member; + + public CompositeTaskVariable(String name, String member) { + this.name = name; + this.member = member; + } + + public CompositeTaskVariable(String name) { + this.name = name; + } + + public CompositeTaskVariable(Ast ast) { + } + + public Ast getAst() { + return null; + } + + public String getName() { + return this.name; + } + + public String getMember() { + return this.member; + } + + public int hashCode() { + return 0; + } + + public boolean equals(CompositeTaskVariable other) { + return false; + } + + public String toString() { + return "[Variable: name=" + this.name + "]"; + } +} diff --git a/wdl/examples/0.wdl b/wdl/examples/0.wdl index a699ba7..6ac7df5 100644 --- a/wdl/examples/0.wdl +++ b/wdl/examples/0.wdl @@ -6,7 +6,7 @@ composite_task foo { for ( item in foo ) { step btask[version=0] { - input: p0=x, p1=s; + input: p0=x, p1=GLOBAL; output: File("bar.txt") as y; } diff --git a/wdl/examples/1.wdl b/wdl/examples/1.wdl index 4d9611b..99e75d5 100644 --- a/wdl/examples/1.wdl +++ b/wdl/examples/1.wdl @@ -6,7 +6,7 @@ composite_task foo { for ( item in foo ) { step btask[version=0] { - input: p0=x, p1=global0; + input: p0=x, p1=global; output: File("bar.txt") as y; } diff --git a/wdl/examples/2.wdl b/wdl/examples/2.wdl new file mode 100644 index 0000000..622a2e6 --- /dev/null +++ b/wdl/examples/2.wdl @@ -0,0 +1,30 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=global; + output: File("bar.txt") appendto list; + } + } + + for ( item in list ) { + step ctask[version=0] { + input: p0=x, p1=item, p2=list, p3=blah; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + + step etask[version=0] { + output: File("blah.txt") as blah; + } + +} diff --git a/wdl/examples/6.wdl b/wdl/examples/6.wdl new file mode 100644 index 0000000..c4371f6 --- /dev/null +++ b/wdl/examples/6.wdl @@ -0,0 +1,12 @@ +composite_task test { + for (item in collection) { + step task[version=0] { + input: p0=x, p1=y, p2=item.z; + output: File("xyz") as list; + } + } + + step task1[version=0] { + input: p0=list; + } +} From 4bc4fdaf6a29a152171224fbc6cfadcf2a78e8ee Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 23 Aug 2012 09:20:20 -0400 Subject: [PATCH 043/140] code compiles now, still not correct though --- wdl/CompositeTask.java | 19 +++++++++++-------- wdl/CompositeTaskForLoop.java | 2 +- wdl/CompositeTaskStep.java | 5 ----- wdl/CompositeTaskStepOutput.java | 8 +++----- wdl/WdlMain.java | 12 ------------ 5 files changed, 15 insertions(+), 31 deletions(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 1aa3660..615b988 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -53,11 +53,11 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { for ( AstNode ctNode : ctNodes ) { Ast node = (Ast) ctNode; if (node.getName().equals("Step")) { - nodes.add(new CompositeTaskStep(ast)); + nodes.add(verify_step(ast)); } else if (node.getName().equals("ForLoop")) { - nodes.add(new CompositeTaskForLoop(ast)); + nodes.add(verify_for(ast)); } else if (node.getName().equals("CompositeTask")) { - nodes.add(new CompositeTaskStep(ast)); + nodes.add(verify_composite_task(ast)); } else { throw new SyntaxError("TODO"); } @@ -141,7 +141,10 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { ctStepName = task_name.getSourceString(); } - return new CompositeTaskStep(ctStepName, ctSubTask); + Set inputs = new HashSet(); + Set outputs = new HashSet(); + + return new CompositeTaskStep(ctStepName, ctSubTask, inputs, outputs); } private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { @@ -159,12 +162,13 @@ private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { Set nodes = new HashSet(); + Terminal ctName = (Terminal) ast.getAttribute("name"); for ( AstNode sub : (AstList) ast.getAttribute("body") ) { nodes.add( verify((Ast) sub) ); } - return new CompositeTask(nodes); + return new CompositeTask(ctName.getSourceString(), nodes); } private Terminal getTaskName(Ast task) { @@ -223,7 +227,7 @@ public String getName() { } public Set getNodes() { - return this.nodes; + return null; } public CompositeTaskStep getStep(String name) { @@ -235,7 +239,7 @@ public CompositeTaskStep getStep(String name) { } private Set getTasks(CompositeTaskScope scope) { - return tasks; + return null; } public Ast getAst() { @@ -247,7 +251,6 @@ public void setName(String name) { } public void addNode(CompositeTaskNode node) { - this.nodes.add(node); } /** Private methods **/ diff --git a/wdl/CompositeTaskForLoop.java b/wdl/CompositeTaskForLoop.java index e2e0a44..a87e66a 100644 --- a/wdl/CompositeTaskForLoop.java +++ b/wdl/CompositeTaskForLoop.java @@ -12,7 +12,7 @@ public CompositeTaskForLoop(String collection, String var, Set Date: Thu, 23 Aug 2012 09:30:48 -0400 Subject: [PATCH 044/140] removing unused and unnecessary code --- wdl/CompositeTask.java | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 615b988..e3a2af3 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -52,15 +52,7 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { for ( AstNode ctNode : ctNodes ) { Ast node = (Ast) ctNode; - if (node.getName().equals("Step")) { - nodes.add(verify_step(ast)); - } else if (node.getName().equals("ForLoop")) { - nodes.add(verify_for(ast)); - } else if (node.getName().equals("CompositeTask")) { - nodes.add(verify_composite_task(ast)); - } else { - throw new SyntaxError("TODO"); - } + nodes.add(verify(ast)); } /* Graph definition: @@ -72,11 +64,11 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { * scope -> step : Step is dependent on scope completing * scope (for) -> variable : Variable is the loop variable (not collection). * Each for loop contains exactly one of these edges - * scope -> scope : Doesn't exist. * variable -> scope (for) : Variable is the loop collection * variable -> step : Step needs variable as an input - * variable -> variable : Doesn't exist. * step -> variable : Variable is an output of step + * variable -> variable : Doesn't exist. + * scope -> scope : Doesn't exist. * step -> scope : Doesn't exist. * step -> step : Doesn't exist. * @@ -85,29 +77,6 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { return composite_task; } - private boolean in_scope(CompositeTaskScope scope, CompositeTaskNode node) { - boolean answer = false; - for ( CompositeTaskNode scope_node : scope.getNodes() ) { - answer |= (node == scope_node); - if ( scope_node instanceof CompositeTaskScope ) { - answer |= in_scope((CompositeTaskScope) scope_node, node); - } - } - return answer; - } - - private String variable_to_string(Ast variable) { - String name; - Terminal asName = (Terminal) variable.getAttribute("name"); - Terminal asMember = (Terminal) variable.getAttribute("member"); - name = asName.getSourceString(); - - if ( false && asMember != null ) { - name += "." + asMember.getSourceString(); - } - return name; - } - private CompositeTaskNode verify(Ast ast) throws SyntaxError { if ( ast.getName().equals("Step") ) { return verify_step(ast); From 1862583a55803adb019f2025fb69724e77893251 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 23 Aug 2012 14:25:37 -0400 Subject: [PATCH 045/140] Compiles & runs, no graph functionality yet --- wdl/CompositeTask.java | 57 ++++++++++++++++++++++++++++++++++++++++++-------- wdl/WdlMain.java | 25 ++++++++++++++++++---- wdl/examples/2.wdl | 2 +- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index e3a2af3..7f52583 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -12,7 +12,7 @@ private ParseTree parse_tree; private Ast ast; private WdlSyntaxErrorFormatter error_formatter; - private Set inputs; + private Set nodes; private String name; private class CompositeTaskAstVerifier { @@ -48,11 +48,11 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { */ AstList ctNodes = (AstList) composite_task.getAttribute("body"); - Set nodes = new HashSet(); + CompositeTask.this.nodes = new HashSet(); for ( AstNode ctNode : ctNodes ) { Ast node = (Ast) ctNode; - nodes.add(verify(ast)); + CompositeTask.this.nodes.add(verify(node)); } /* Graph definition: @@ -77,6 +77,12 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { return composite_task; } + private CompositeTaskVariable ast_to_variable(Ast ast) { + Terminal name = (Terminal) ast.getAttribute("name"); + Terminal member = (Terminal) ast.getAttribute("member"); + return new CompositeTaskVariable(name.getSourceString(), (member == null) ? null : member.getSourceString()); + } + private CompositeTaskNode verify(Ast ast) throws SyntaxError { if ( ast.getName().equals("Step") ) { return verify_step(ast); @@ -98,22 +104,50 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); } - CompositeTaskSubTask ctSubTask = new CompositeTaskSubTask( + CompositeTaskSubTask subtask = new CompositeTaskSubTask( task_name.getSourceString(), task_version.getSourceString() ); - String ctStepName; + String name; if ( step.getAttribute("name") != null ) { - ctStepName = ((Terminal) step.getAttribute("name")).getSourceString(); + name = ((Terminal) step.getAttribute("name")).getSourceString(); } else { - ctStepName = task_name.getSourceString(); + name = task_name.getSourceString(); } Set inputs = new HashSet(); Set outputs = new HashSet(); - return new CompositeTaskStep(ctStepName, ctSubTask, inputs, outputs); + AstList body = (AstList) step.getAttribute("body"); + + if ( body != null ) { + for ( AstNode entry : body ) { + Ast entry_ast = (Ast) entry; + + if ( entry_ast.getName().equals("StepInputList") ) { + AstList input_list = (AstList) entry_ast.getAttribute("inputs"); + for ( AstNode input_node : input_list ) { + Ast input = (Ast) input_node; + Terminal parameter = (Terminal) input.getAttribute("parameter"); + CompositeTaskVariable variable = ast_to_variable((Ast) input.getAttribute("value")); + inputs.add( new CompositeTaskStepInput(parameter.getSourceString(), variable) ); + } + } + + if ( entry_ast.getName().equals("StepOutputList") ) { + AstList output_list = (AstList) entry_ast.getAttribute("outputs"); + for ( AstNode output_node : output_list ) { + Ast output = (Ast) output_node; + Terminal filepath = (Terminal) output.getAttribute("file"); + CompositeTaskVariable variable = ast_to_variable((Ast) output.getAttribute("as")); + outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); + } + } + } + } + + return new CompositeTaskStep(name, subtask, inputs, outputs); } private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { @@ -165,6 +199,7 @@ private Terminal getTaskVersion(Ast task) { CompositeTask(String name, Set nodes) { this.name = name; + this.nodes = nodes; } CompositeTask(SourceCode source_code) throws SyntaxError { @@ -196,7 +231,7 @@ public String getName() { } public Set getNodes() { - return null; + return this.nodes; } public CompositeTaskStep getStep(String name) { @@ -222,6 +257,10 @@ public void setName(String name) { public void addNode(CompositeTaskNode node) { } + public String toString() { + return "[CompositeTask name="+this.name+"]"; + } + /** Private methods **/ private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index 1e0f01c..9d78825 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -7,7 +7,7 @@ class WdlMain { public static void usage() { - System.err.println("Usage: java ParserMain <.wdl file> "); + System.err.println("Usage: java ParserMain <.wdl file> "); System.exit(-1); } @@ -18,15 +18,18 @@ public static void main(String[] args) { } try { - CompositeTask wdl = new CompositeTask(new File(args[0])); + CompositeTask ctask = new CompositeTask(new File(args[0])); if ( args[1].equals("ast") ) { - Ast ast = wdl.getAst(); + Ast ast = ctask.getAst(); System.out.println(ast.toPrettyString()); } else if ( args[1].equals("parsetree") ) { - ParseTree tree = wdl.getParseTree(); + ParseTree tree = ctask.getParseTree(); System.out.println(tree.toPrettyString()); + } else if ( args[1].equals("entities") ) { + print_tree(ctask); } else if ( args[1].equals("graph") ) { + System.out.println(ctask); } else { usage(); } @@ -38,4 +41,18 @@ public static void main(String[] args) { System.exit(-1); } } + + public static void print_tree(CompositeTask ctask) { + print_tree(ctask, 0); + } + + public static void print_tree(CompositeTaskScope scope, int depth) { + Set nodes = scope.getNodes(); + for ( CompositeTaskNode node : nodes ) { + System.out.println(Utility.getIndentString(depth) + node); + if ( node instanceof CompositeTaskScope ) { + print_tree((CompositeTaskScope) node, depth + 2); + } + } + } } diff --git a/wdl/examples/2.wdl b/wdl/examples/2.wdl index 622a2e6..0f6c450 100644 --- a/wdl/examples/2.wdl +++ b/wdl/examples/2.wdl @@ -7,7 +7,7 @@ composite_task foo { for ( item in foo ) { step btask[version=0] { input: p0=x, p1=global; - output: File("bar.txt") appendto list; + output: File("bar.txt") as list; } } From 9ce0503f26827bc3b9e8480d2126481230bed067 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 23 Aug 2012 15:57:04 -0400 Subject: [PATCH 046/140] adding jgrapht --- wdl/org/jgrapht/DirectedGraph.java | 108 ++ wdl/org/jgrapht/EdgeFactory.java | 66 ++ wdl/org/jgrapht/Graph.java | 435 +++++++ wdl/org/jgrapht/GraphHelper.java | 59 + wdl/org/jgrapht/GraphMapping.java | 75 ++ wdl/org/jgrapht/GraphPath.java | 105 ++ wdl/org/jgrapht/Graphs.java | 442 +++++++ wdl/org/jgrapht/ListenableGraph.java | 90 ++ wdl/org/jgrapht/UndirectedGraph.java | 70 ++ wdl/org/jgrapht/VertexFactory.java | 63 + wdl/org/jgrapht/WeightedGraph.java | 71 ++ wdl/org/jgrapht/alg/AbstractPathElement.java | 202 ++++ wdl/org/jgrapht/alg/AbstractPathElementList.java | 196 ++++ wdl/org/jgrapht/alg/BellmanFordIterator.java | 448 +++++++ wdl/org/jgrapht/alg/BellmanFordPathElement.java | 150 +++ wdl/org/jgrapht/alg/BellmanFordShortestPath.java | 239 ++++ wdl/org/jgrapht/alg/BiconnectivityInspector.java | 138 +++ wdl/org/jgrapht/alg/BlockCutpointGraph.java | 365 ++++++ wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java | 198 ++++ wdl/org/jgrapht/alg/ChromaticNumber.java | 147 +++ wdl/org/jgrapht/alg/ConnectivityInspector.java | 302 +++++ wdl/org/jgrapht/alg/CycleDetector.java | 271 +++++ wdl/org/jgrapht/alg/DijkstraShortestPath.java | 218 ++++ wdl/org/jgrapht/alg/DirectedNeighborIndex.java | 233 ++++ wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java | 194 ++++ wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java | 361 ++++++ wdl/org/jgrapht/alg/EulerianCircuit.java | 148 +++ .../jgrapht/alg/FloydWarshallShortestPaths.java | 317 +++++ wdl/org/jgrapht/alg/HamiltonianCycle.java | 120 ++ wdl/org/jgrapht/alg/KShortestPaths.java | 258 +++++ wdl/org/jgrapht/alg/KShortestPathsIterator.java | 416 +++++++ .../jgrapht/alg/KruskalMinimumSpanningTree.java | 126 ++ wdl/org/jgrapht/alg/NeighborIndex.java | 262 +++++ wdl/org/jgrapht/alg/RankingPathElement.java | 115 ++ wdl/org/jgrapht/alg/RankingPathElementList.java | 436 +++++++ wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java | 283 +++++ .../jgrapht/alg/StrongConnectivityInspector.java | 393 +++++++ wdl/org/jgrapht/alg/TransitiveClosure.java | 138 +++ wdl/org/jgrapht/alg/VertexCovers.java | 157 +++ wdl/org/jgrapht/alg/package.html | 6 + wdl/org/jgrapht/alg/util/UnionFind.java | 168 +++ .../jgrapht/alg/util/VertexDegreeComparator.java | 134 +++ wdl/org/jgrapht/alg/util/package.html | 6 + .../event/ConnectedComponentTraversalEvent.java | 103 ++ wdl/org/jgrapht/event/EdgeTraversalEvent.java | 93 ++ wdl/org/jgrapht/event/GraphChangeEvent.java | 93 ++ wdl/org/jgrapht/event/GraphEdgeChangeEvent.java | 169 +++ wdl/org/jgrapht/event/GraphListener.java | 74 ++ wdl/org/jgrapht/event/GraphVertexChangeEvent.java | 119 ++ wdl/org/jgrapht/event/TraversalListener.java | 100 ++ .../jgrapht/event/TraversalListenerAdapter.java | 93 ++ wdl/org/jgrapht/event/VertexSetListener.java | 77 ++ wdl/org/jgrapht/event/VertexTraversalEvent.java | 93 ++ wdl/org/jgrapht/event/package.html | 7 + wdl/org/jgrapht/experimental/GraphReader.java | 181 +++ wdl/org/jgrapht/experimental/GraphSquare.java | 219 ++++ wdl/org/jgrapht/experimental/GraphTests.java | 118 ++ .../experimental/PartiteRandomGraphGenerator.java | 171 +++ .../jgrapht/experimental/RandomGraphHelper.java | 126 ++ .../experimental/UniformRandomGraphGenerator.java | 115 ++ .../experimental/alg/ApproximationAlgorithm.java | 17 + .../jgrapht/experimental/alg/ExactAlgorithm.java | 13 + .../experimental/alg/IntArrayGraphAlgorithm.java | 49 + .../alg/color/BrownBacktrackColoring.java | 99 ++ .../experimental/alg/color/GreedyColoring.java | 185 +++ .../experimental/dag/DirectedAcyclicGraph.java | 1199 +++++++++++++++++++ .../equivalence/EquivalenceComparator.java | 93 ++ .../equivalence/EquivalenceComparatorChain.java | 71 ++ .../EquivalenceComparatorChainBase.java | 167 +++ .../experimental/equivalence/EquivalenceSet.java | 206 ++++ .../equivalence/EquivalenceSetCreator.java | 262 +++++ .../equivalence/UniformEquivalenceComparator.java | 80 ++ .../jgrapht/experimental/equivalence/package.html | 6 + .../AbstractExhaustiveIsomorphismInspector.java | 423 +++++++ .../AdaptiveIsomorphismInspectorFactory.java | 268 +++++ .../EquivalenceIsomorphismInspector.java | 325 ++++++ .../isomorphism/GraphIsomorphismInspector.java | 95 ++ .../experimental/isomorphism/GraphOrdering.java | 232 ++++ .../isomorphism/IsomorphismRelation.java | 151 +++ .../PermutationIsomorphismInspector.java | 148 +++ .../VertexDegreeEquivalenceComparator.java | 178 +++ .../jgrapht/experimental/isomorphism/package.html | 6 + wdl/org/jgrapht/experimental/package.html | 11 + .../permutation/ArrayPermutationsIter.java | 56 + .../permutation/CollectionPermutationIter.java | 185 +++ .../permutation/CompoundPermutationIter.java | 307 +++++ .../permutation/IntegerPermutationIter.java | 311 +++++ .../permutation/PermutationFactory.java | 98 ++ .../jgrapht/experimental/permutation/package.html | 6 + .../generate/CompleteBipartiteGraphGenerator.java | 119 ++ .../jgrapht/generate/CompleteGraphGenerator.java | 139 +++ wdl/org/jgrapht/generate/EmptyGraphGenerator.java | 95 ++ wdl/org/jgrapht/generate/GraphGenerator.java | 80 ++ wdl/org/jgrapht/generate/GridGraphGenerator.java | 145 +++ .../jgrapht/generate/HyperCubeGraphGenerator.java | 118 ++ wdl/org/jgrapht/generate/LinearGraphGenerator.java | 124 ++ wdl/org/jgrapht/generate/RandomGraphGenerator.java | 381 ++++++ wdl/org/jgrapht/generate/RingGraphGenerator.java | 106 ++ .../jgrapht/generate/ScaleFreeGraphGenerator.java | 154 +++ wdl/org/jgrapht/generate/StarGraphGenerator.java | 116 ++ wdl/org/jgrapht/generate/WheelGraphGenerator.java | 155 +++ wdl/org/jgrapht/generate/package.html | 6 + wdl/org/jgrapht/graph/AbstractBaseGraph.java | 1222 ++++++++++++++++++++ wdl/org/jgrapht/graph/AbstractGraph.java | 322 ++++++ wdl/org/jgrapht/graph/AsUndirectedGraph.java | 209 ++++ .../jgrapht/graph/AsUnweightedDirectedGraph.java | 100 ++ wdl/org/jgrapht/graph/AsUnweightedGraph.java | 100 ++ wdl/org/jgrapht/graph/AsWeightedGraph.java | 147 +++ wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java | 91 ++ wdl/org/jgrapht/graph/ClassBasedVertexFactory.java | 79 ++ wdl/org/jgrapht/graph/DefaultDirectedGraph.java | 86 ++ .../graph/DefaultDirectedWeightedGraph.java | 85 ++ wdl/org/jgrapht/graph/DefaultEdge.java | 91 ++ wdl/org/jgrapht/graph/DefaultGraphMapping.java | 135 +++ wdl/org/jgrapht/graph/DefaultListenableGraph.java | 524 +++++++++ wdl/org/jgrapht/graph/DefaultWeightedEdge.java | 77 ++ wdl/org/jgrapht/graph/DirectedGraphUnion.java | 109 ++ wdl/org/jgrapht/graph/DirectedMaskSubgraph.java | 64 + wdl/org/jgrapht/graph/DirectedMultigraph.java | 82 ++ wdl/org/jgrapht/graph/DirectedPseudograph.java | 80 ++ wdl/org/jgrapht/graph/DirectedSubgraph.java | 158 +++ .../jgrapht/graph/DirectedWeightedMultigraph.java | 84 ++ .../jgrapht/graph/DirectedWeightedSubgraph.java | 83 ++ wdl/org/jgrapht/graph/EdgeReversedGraph.java | 187 +++ wdl/org/jgrapht/graph/EdgeSetFactory.java | 73 ++ wdl/org/jgrapht/graph/GraphDelegator.java | 298 +++++ wdl/org/jgrapht/graph/GraphPathImpl.java | 122 ++ wdl/org/jgrapht/graph/GraphUnion.java | 288 +++++ wdl/org/jgrapht/graph/IntrusiveEdge.java | 82 ++ wdl/org/jgrapht/graph/ListenableDirectedGraph.java | 83 ++ .../graph/ListenableDirectedWeightedGraph.java | 84 ++ .../jgrapht/graph/ListenableUndirectedGraph.java | 83 ++ .../graph/ListenableUndirectedWeightedGraph.java | 85 ++ wdl/org/jgrapht/graph/MaskEdgeSet.java | 149 +++ wdl/org/jgrapht/graph/MaskFunctor.java | 72 ++ wdl/org/jgrapht/graph/MaskSubgraph.java | 298 +++++ wdl/org/jgrapht/graph/MaskVertexSet.java | 134 +++ wdl/org/jgrapht/graph/Multigraph.java | 85 ++ wdl/org/jgrapht/graph/ParanoidGraph.java | 110 ++ wdl/org/jgrapht/graph/Pseudograph.java | 84 ++ wdl/org/jgrapht/graph/SimpleDirectedGraph.java | 82 ++ .../jgrapht/graph/SimpleDirectedWeightedGraph.java | 83 ++ wdl/org/jgrapht/graph/SimpleGraph.java | 85 ++ wdl/org/jgrapht/graph/SimpleWeightedGraph.java | 82 ++ wdl/org/jgrapht/graph/Subgraph.java | 546 +++++++++ wdl/org/jgrapht/graph/UndirectedGraphUnion.java | 81 ++ wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java | 64 + wdl/org/jgrapht/graph/UndirectedSubgraph.java | 106 ++ .../jgrapht/graph/UndirectedWeightedSubgraph.java | 82 ++ .../jgrapht/graph/UnmodifiableDirectedGraph.java | 74 ++ wdl/org/jgrapht/graph/UnmodifiableGraph.java | 164 +++ .../jgrapht/graph/UnmodifiableUndirectedGraph.java | 74 ++ wdl/org/jgrapht/graph/WeightedMultigraph.java | 85 ++ wdl/org/jgrapht/graph/WeightedPseudograph.java | 85 ++ wdl/org/jgrapht/graph/package.html | 6 + wdl/org/jgrapht/package.html | 7 + .../jgrapht/traverse/AbstractGraphIterator.java | 217 ++++ wdl/org/jgrapht/traverse/BreadthFirstIterator.java | 130 +++ wdl/org/jgrapht/traverse/ClosestFirstIterator.java | 338 ++++++ .../jgrapht/traverse/CrossComponentIterator.java | 570 +++++++++ wdl/org/jgrapht/traverse/DepthFirstIterator.java | 223 ++++ wdl/org/jgrapht/traverse/GraphIterator.java | 114 ++ .../jgrapht/traverse/TopologicalOrderIterator.java | 277 +++++ wdl/org/jgrapht/traverse/package.html | 6 + wdl/org/jgrapht/util/ArrayUnenforcedSet.java | 112 ++ wdl/org/jgrapht/util/FibonacciHeap.java | 611 ++++++++++ wdl/org/jgrapht/util/FibonacciHeapNode.java | 154 +++ wdl/org/jgrapht/util/MathUtil.java | 61 + wdl/org/jgrapht/util/ModifiableInteger.java | 261 +++++ wdl/org/jgrapht/util/PrefetchIterator.java | 223 ++++ wdl/org/jgrapht/util/TypeUtil.java | 67 ++ wdl/org/jgrapht/util/VertexPair.java | 132 +++ wdl/org/jgrapht/util/WeightCombiner.java | 116 ++ wdl/org/jgrapht/util/package.html | 7 + 174 files changed, 29235 insertions(+) create mode 100644 wdl/org/jgrapht/DirectedGraph.java create mode 100644 wdl/org/jgrapht/EdgeFactory.java create mode 100644 wdl/org/jgrapht/Graph.java create mode 100644 wdl/org/jgrapht/GraphHelper.java create mode 100644 wdl/org/jgrapht/GraphMapping.java create mode 100644 wdl/org/jgrapht/GraphPath.java create mode 100644 wdl/org/jgrapht/Graphs.java create mode 100644 wdl/org/jgrapht/ListenableGraph.java create mode 100644 wdl/org/jgrapht/UndirectedGraph.java create mode 100644 wdl/org/jgrapht/VertexFactory.java create mode 100644 wdl/org/jgrapht/WeightedGraph.java create mode 100644 wdl/org/jgrapht/alg/AbstractPathElement.java create mode 100644 wdl/org/jgrapht/alg/AbstractPathElementList.java create mode 100644 wdl/org/jgrapht/alg/BellmanFordIterator.java create mode 100644 wdl/org/jgrapht/alg/BellmanFordPathElement.java create mode 100644 wdl/org/jgrapht/alg/BellmanFordShortestPath.java create mode 100644 wdl/org/jgrapht/alg/BiconnectivityInspector.java create mode 100644 wdl/org/jgrapht/alg/BlockCutpointGraph.java create mode 100644 wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java create mode 100644 wdl/org/jgrapht/alg/ChromaticNumber.java create mode 100644 wdl/org/jgrapht/alg/ConnectivityInspector.java create mode 100644 wdl/org/jgrapht/alg/CycleDetector.java create mode 100644 wdl/org/jgrapht/alg/DijkstraShortestPath.java create mode 100644 wdl/org/jgrapht/alg/DirectedNeighborIndex.java create mode 100644 wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java create mode 100644 wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java create mode 100644 wdl/org/jgrapht/alg/EulerianCircuit.java create mode 100644 wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java create mode 100644 wdl/org/jgrapht/alg/HamiltonianCycle.java create mode 100644 wdl/org/jgrapht/alg/KShortestPaths.java create mode 100644 wdl/org/jgrapht/alg/KShortestPathsIterator.java create mode 100644 wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java create mode 100644 wdl/org/jgrapht/alg/NeighborIndex.java create mode 100644 wdl/org/jgrapht/alg/RankingPathElement.java create mode 100644 wdl/org/jgrapht/alg/RankingPathElementList.java create mode 100644 wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java create mode 100644 wdl/org/jgrapht/alg/StrongConnectivityInspector.java create mode 100644 wdl/org/jgrapht/alg/TransitiveClosure.java create mode 100644 wdl/org/jgrapht/alg/VertexCovers.java create mode 100644 wdl/org/jgrapht/alg/package.html create mode 100644 wdl/org/jgrapht/alg/util/UnionFind.java create mode 100644 wdl/org/jgrapht/alg/util/VertexDegreeComparator.java create mode 100644 wdl/org/jgrapht/alg/util/package.html create mode 100644 wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java create mode 100644 wdl/org/jgrapht/event/EdgeTraversalEvent.java create mode 100644 wdl/org/jgrapht/event/GraphChangeEvent.java create mode 100644 wdl/org/jgrapht/event/GraphEdgeChangeEvent.java create mode 100644 wdl/org/jgrapht/event/GraphListener.java create mode 100644 wdl/org/jgrapht/event/GraphVertexChangeEvent.java create mode 100644 wdl/org/jgrapht/event/TraversalListener.java create mode 100644 wdl/org/jgrapht/event/TraversalListenerAdapter.java create mode 100644 wdl/org/jgrapht/event/VertexSetListener.java create mode 100644 wdl/org/jgrapht/event/VertexTraversalEvent.java create mode 100644 wdl/org/jgrapht/event/package.html create mode 100644 wdl/org/jgrapht/experimental/GraphReader.java create mode 100644 wdl/org/jgrapht/experimental/GraphSquare.java create mode 100644 wdl/org/jgrapht/experimental/GraphTests.java create mode 100644 wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java create mode 100644 wdl/org/jgrapht/experimental/RandomGraphHelper.java create mode 100644 wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java create mode 100644 wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java create mode 100644 wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java create mode 100644 wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java create mode 100644 wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java create mode 100644 wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java create mode 100644 wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java create mode 100644 wdl/org/jgrapht/experimental/equivalence/package.html create mode 100644 wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java create mode 100644 wdl/org/jgrapht/experimental/isomorphism/package.html create mode 100644 wdl/org/jgrapht/experimental/package.html create mode 100644 wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java create mode 100644 wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java create mode 100644 wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java create mode 100644 wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java create mode 100644 wdl/org/jgrapht/experimental/permutation/PermutationFactory.java create mode 100644 wdl/org/jgrapht/experimental/permutation/package.html create mode 100644 wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java create mode 100755 wdl/org/jgrapht/generate/CompleteGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/EmptyGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/GraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/GridGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/LinearGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/RandomGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/RingGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/StarGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/WheelGraphGenerator.java create mode 100644 wdl/org/jgrapht/generate/package.html create mode 100644 wdl/org/jgrapht/graph/AbstractBaseGraph.java create mode 100644 wdl/org/jgrapht/graph/AbstractGraph.java create mode 100644 wdl/org/jgrapht/graph/AsUndirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/AsUnweightedGraph.java create mode 100644 wdl/org/jgrapht/graph/AsWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java create mode 100644 wdl/org/jgrapht/graph/ClassBasedVertexFactory.java create mode 100644 wdl/org/jgrapht/graph/DefaultDirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/DefaultEdge.java create mode 100644 wdl/org/jgrapht/graph/DefaultGraphMapping.java create mode 100644 wdl/org/jgrapht/graph/DefaultListenableGraph.java create mode 100644 wdl/org/jgrapht/graph/DefaultWeightedEdge.java create mode 100644 wdl/org/jgrapht/graph/DirectedGraphUnion.java create mode 100644 wdl/org/jgrapht/graph/DirectedMaskSubgraph.java create mode 100644 wdl/org/jgrapht/graph/DirectedMultigraph.java create mode 100644 wdl/org/jgrapht/graph/DirectedPseudograph.java create mode 100644 wdl/org/jgrapht/graph/DirectedSubgraph.java create mode 100644 wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java create mode 100644 wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java create mode 100644 wdl/org/jgrapht/graph/EdgeReversedGraph.java create mode 100644 wdl/org/jgrapht/graph/EdgeSetFactory.java create mode 100644 wdl/org/jgrapht/graph/GraphDelegator.java create mode 100644 wdl/org/jgrapht/graph/GraphPathImpl.java create mode 100644 wdl/org/jgrapht/graph/GraphUnion.java create mode 100644 wdl/org/jgrapht/graph/IntrusiveEdge.java create mode 100644 wdl/org/jgrapht/graph/ListenableDirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/ListenableUndirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/MaskEdgeSet.java create mode 100644 wdl/org/jgrapht/graph/MaskFunctor.java create mode 100644 wdl/org/jgrapht/graph/MaskSubgraph.java create mode 100644 wdl/org/jgrapht/graph/MaskVertexSet.java create mode 100644 wdl/org/jgrapht/graph/Multigraph.java create mode 100644 wdl/org/jgrapht/graph/ParanoidGraph.java create mode 100644 wdl/org/jgrapht/graph/Pseudograph.java create mode 100644 wdl/org/jgrapht/graph/SimpleDirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/SimpleGraph.java create mode 100644 wdl/org/jgrapht/graph/SimpleWeightedGraph.java create mode 100644 wdl/org/jgrapht/graph/Subgraph.java create mode 100644 wdl/org/jgrapht/graph/UndirectedGraphUnion.java create mode 100644 wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java create mode 100644 wdl/org/jgrapht/graph/UndirectedSubgraph.java create mode 100644 wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java create mode 100644 wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/UnmodifiableGraph.java create mode 100644 wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java create mode 100644 wdl/org/jgrapht/graph/WeightedMultigraph.java create mode 100644 wdl/org/jgrapht/graph/WeightedPseudograph.java create mode 100644 wdl/org/jgrapht/graph/package.html create mode 100644 wdl/org/jgrapht/package.html create mode 100644 wdl/org/jgrapht/traverse/AbstractGraphIterator.java create mode 100644 wdl/org/jgrapht/traverse/BreadthFirstIterator.java create mode 100644 wdl/org/jgrapht/traverse/ClosestFirstIterator.java create mode 100644 wdl/org/jgrapht/traverse/CrossComponentIterator.java create mode 100644 wdl/org/jgrapht/traverse/DepthFirstIterator.java create mode 100644 wdl/org/jgrapht/traverse/GraphIterator.java create mode 100644 wdl/org/jgrapht/traverse/TopologicalOrderIterator.java create mode 100644 wdl/org/jgrapht/traverse/package.html create mode 100644 wdl/org/jgrapht/util/ArrayUnenforcedSet.java create mode 100644 wdl/org/jgrapht/util/FibonacciHeap.java create mode 100644 wdl/org/jgrapht/util/FibonacciHeapNode.java create mode 100644 wdl/org/jgrapht/util/MathUtil.java create mode 100644 wdl/org/jgrapht/util/ModifiableInteger.java create mode 100644 wdl/org/jgrapht/util/PrefetchIterator.java create mode 100644 wdl/org/jgrapht/util/TypeUtil.java create mode 100644 wdl/org/jgrapht/util/VertexPair.java create mode 100644 wdl/org/jgrapht/util/WeightCombiner.java create mode 100644 wdl/org/jgrapht/util/package.html diff --git a/wdl/org/jgrapht/DirectedGraph.java b/wdl/org/jgrapht/DirectedGraph.java new file mode 100644 index 0000000..aa4d5b5 --- /dev/null +++ b/wdl/org/jgrapht/DirectedGraph.java @@ -0,0 +1,108 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * DirectedGraph.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * + */ +package org.jgrapht; + +import java.util.*; + + +/** + * A graph whose all edges are directed. This is the root interface of all + * directed graphs. + * + *

See + * http://mathworld.wolfram.com/DirectedGraph.html for more on directed + * graphs.

+ * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public interface DirectedGraph + extends Graph +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the "in degree" of the specified vertex. An in degree of a vertex + * in a directed graph is the number of inward directed edges from that + * vertex. See + * http://mathworld.wolfram.com/Indegree.html. + * + * @param vertex vertex whose degree is to be calculated. + * + * @return the degree of the specified vertex. + */ + public int inDegreeOf(V vertex); + + /** + * Returns a set of all edges incoming into the specified vertex. + * + * @param vertex the vertex for which the list of incoming edges to be + * returned. + * + * @return a set of all edges incoming into the specified vertex. + */ + public Set incomingEdgesOf(V vertex); + + /** + * Returns the "out degree" of the specified vertex. An out degree of a + * vertex in a directed graph is the number of outward directed edges from + * that vertex. See + * http://mathworld.wolfram.com/Outdegree.html. + * + * @param vertex vertex whose degree is to be calculated. + * + * @return the degree of the specified vertex. + */ + public int outDegreeOf(V vertex); + + /** + * Returns a set of all edges outgoing from the specified vertex. + * + * @param vertex the vertex for which the list of outgoing edges to be + * returned. + * + * @return a set of all edges outgoing from the specified vertex. + */ + public Set outgoingEdgesOf(V vertex); +} + +// End DirectedGraph.java diff --git a/wdl/org/jgrapht/EdgeFactory.java b/wdl/org/jgrapht/EdgeFactory.java new file mode 100644 index 0000000..c9b82af --- /dev/null +++ b/wdl/org/jgrapht/EdgeFactory.java @@ -0,0 +1,66 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * EdgeFactory.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht; + +/** + * An edge factory used by graphs for creating new edges. + * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public interface EdgeFactory +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Creates a new edge whose endpoints are the specified source and target + * vertices. + * + * @param sourceVertex the source vertex. + * @param targetVertex the target vertex. + * + * @return a new edge whose endpoints are the specified source and target + * vertices. + */ + public E createEdge(V sourceVertex, V targetVertex); +} + +// End EdgeFactory.java diff --git a/wdl/org/jgrapht/Graph.java b/wdl/org/jgrapht/Graph.java new file mode 100644 index 0000000..18ab404 --- /dev/null +++ b/wdl/org/jgrapht/Graph.java @@ -0,0 +1,435 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------- + * Graph.java + * ---------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): John V. Sichi + * Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 06-Nov-2003 : Change edge sharing semantics (JVS); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht; + +import java.util.*; + + +/** + * The root interface in the graph hierarchy. A mathematical graph-theory graph + * object G(V,E) contains a set V of vertices and a set + * E of edges. Each edge e=(v1,v2) in E connects vertex v1 to vertex v2. + * for more information about graphs and their related definitions see + * http://mathworld.wolfram.com/Graph.html. + * + *

This library generally follows the terminology found at: + * http://mathworld.wolfram.com/topics/GraphTheory.html. Implementation of + * this interface can provide simple-graphs, multigraphs, pseudographs etc. The + * package org.jgrapht.graph provides a gallery of abstract and + * concrete graph implementations.

+ * + *

This library works best when vertices represent arbitrary objects and + * edges represent the relationships between them. Vertex and edge instances may + * be shared by more than one graph.

+ * + *

Through generics, a graph can be typed to specific classes for vertices + * V and edges E<T>. Such a graph can contain + * vertices of type V and all sub-types and Edges of type + * E and all sub-types.

+ * + *

For guidelines on vertex and edge classes, see this wiki + * page. + * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public interface Graph +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Returns a set of all edges connecting source vertex to target vertex if + * such vertices exist in this graph. If any of the vertices does not exist + * or is null, returns null. If both vertices + * exist but no edges found, returns an empty set. + * + *

In undirected graphs, some of the returned edges may have their source + * and target vertices in the opposite order. In simple graphs the returned + * set is either singleton set or empty set.

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return a set of all edges connecting source vertex to target vertex. + */ + public Set getAllEdges(V sourceVertex, V targetVertex); + + /** + * Returns an edge connecting source vertex to target vertex if such + * vertices and such edge exist in this graph. Otherwise returns + * null. If any of the specified vertices is null + * returns null + * + *

In undirected graphs, the returned edge may have its source and target + * vertices in the opposite order.

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return an edge connecting source vertex to target vertex. + */ + public E getEdge(V sourceVertex, V targetVertex); + + /** + * Returns the edge factory using which this graph creates new edges. The + * edge factory is defined when the graph is constructed and must not be + * modified. + * + * @return the edge factory using which this graph creates new edges. + */ + public EdgeFactory getEdgeFactory(); + + /** + * Creates a new edge in this graph, going from the source vertex to the + * target vertex, and returns the created edge. Some graphs do not allow + * edge-multiplicity. In such cases, if the graph already contains an edge + * from the specified source to the specified target, than this method does + * not change the graph and returns null. + * + *

The source and target vertices must already be contained in this + * graph. If they are not found in graph IllegalArgumentException is + * thrown.

+ * + *

This method creates the new edge e using this graph's + * EdgeFactory. For the new edge to be added e + * must not be equal to any other edge the graph (even if the graph + * allows edge-multiplicity). More formally, the graph must not contain any + * edge e2 such that e2.equals(e). If such + * e2 is found then the newly created edge e is + * abandoned, the method leaves this graph unchanged returns + * null.

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return The newly created edge if added to the graph, otherwise + * null. + * + * @throws IllegalArgumentException if source or target vertices are not + * found in the graph. + * @throws NullPointerException if any of the specified vertices is + * null. + * + * @see #getEdgeFactory() + */ + public E addEdge(V sourceVertex, V targetVertex); + + /** + * Adds the specified edge to this graph, going from the source vertex to + * the target vertex. More formally, adds the specified edge, + * e, to this graph if this graph contains no edge e2 + * such that e2.equals(e). If this graph already contains such + * an edge, the call leaves this graph unchanged and returns false. + * Some graphs do not allow edge-multiplicity. In such cases, if the graph + * already contains an edge from the specified source to the specified + * target, than this method does not change the graph and returns + * false. If the edge was added to the graph, returns + * true. + * + *

The source and target vertices must already be contained in this + * graph. If they are not found in graph IllegalArgumentException is + * thrown.

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @param e edge to be added to this graph. + * + * @return true if this graph did not already contain the specified + * edge. + * + * @throws IllegalArgumentException if source or target vertices are not + * found in the graph. + * @throws ClassCastException if the specified edge is not assignment + * compatible with the class of edges produced by the edge factory of this + * graph. + * @throws NullPointerException if any of the specified vertices is + * null. + * + * @see #addEdge(Object, Object) + * @see #getEdgeFactory() + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e); + + /** + * Adds the specified vertex to this graph if not already present. More + * formally, adds the specified vertex, v, to this graph if + * this graph contains no vertex u such that + * u.equals(v). If this graph already contains such vertex, the call + * leaves this graph unchanged and returns false. In combination + * with the restriction on constructors, this ensures that graphs never + * contain duplicate vertices. + * + * @param v vertex to be added to this graph. + * + * @return true if this graph did not already contain the specified + * vertex. + * + * @throws NullPointerException if the specified vertex is + * null. + */ + public boolean addVertex(V v); + + /** + * Returns true if and only if this graph contains an edge going + * from the source vertex to the target vertex. In undirected graphs the + * same result is obtained when source and target are inverted. If any of + * the specified vertices does not exist in the graph, or if is + * null, returns false. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return true if this graph contains the specified edge. + */ + public boolean containsEdge(V sourceVertex, V targetVertex); + + /** + * Returns true if this graph contains the specified edge. More + * formally, returns true if and only if this graph contains an + * edge e2 such that e.equals(e2). If the + * specified edge is null returns false. + * + * @param e edge whose presence in this graph is to be tested. + * + * @return true if this graph contains the specified edge. + */ + public boolean containsEdge(E e); + + /** + * Returns true if this graph contains the specified vertex. More + * formally, returns true if and only if this graph contains a + * vertex u such that u.equals(v). If the + * specified vertex is null returns false. + * + * @param v vertex whose presence in this graph is to be tested. + * + * @return true if this graph contains the specified vertex. + */ + public boolean containsVertex(V v); + + /** + * Returns a set of the edges contained in this graph. The set is backed by + * the graph, so changes to the graph are reflected in the set. If the graph + * is modified while an iteration over the set is in progress, the results + * of the iteration are undefined. + * + *

The graph implementation may maintain a particular set ordering (e.g. + * via {@link java.util.LinkedHashSet}) for deterministic iteration, but + * this is not required. It is the responsibility of callers who rely on + * this behavior to only use graph implementations which support it.

+ * + * @return a set of the edges contained in this graph. + */ + public Set edgeSet(); + + /** + * Returns a set of all edges touching the specified vertex. If no edges are + * touching the specified vertex returns an empty set. + * + * @param vertex the vertex for which a set of touching edges is to be + * returned. + * + * @return a set of all edges touching the specified vertex. + * + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + public Set edgesOf(V vertex); + + /** + * Removes all the edges in this graph that are also contained in the + * specified edge collection. After this call returns, this graph will + * contain no edges in common with the specified edges. This method will + * invoke the {@link #removeEdge(Object)} method. + * + * @param edges edges to be removed from this graph. + * + * @return true if this graph changed as a result of the call + * + * @throws NullPointerException if the specified edge collection is + * null. + * + * @see #removeEdge(Object) + * @see #containsEdge(Object) + */ + public boolean removeAllEdges(Collection edges); + + /** + * Removes all the edges going from the specified source vertex to the + * specified target vertex, and returns a set of all removed edges. Returns + * null if any of the specified vertices does not exist in the + * graph. If both vertices exist but no edge is found, returns an empty set. + * This method will either invoke the {@link #removeEdge(Object)} method, or + * the {@link #removeEdge(Object, Object)} method. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return the removed edges, or null if no either vertex not + * part of graph + */ + public Set removeAllEdges(V sourceVertex, V targetVertex); + + /** + * Removes all the vertices in this graph that are also contained in the + * specified vertex collection. After this call returns, this graph will + * contain no vertices in common with the specified vertices. This method + * will invoke the {@link #removeVertex(Object)} method. + * + * @param vertices vertices to be removed from this graph. + * + * @return true if this graph changed as a result of the call + * + * @throws NullPointerException if the specified vertex collection is + * null. + * + * @see #removeVertex(Object) + * @see #containsVertex(Object) + */ + public boolean removeAllVertices(Collection vertices); + + /** + * Removes an edge going from source vertex to target vertex, if such + * vertices and such edge exist in this graph. Returns the edge if removed + * or null otherwise. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return The removed edge, or null if no edge removed. + */ + public E removeEdge(V sourceVertex, V targetVertex); + + /** + * Removes the specified edge from the graph. Removes the specified edge + * from this graph if it is present. More formally, removes an edge + * e2 such that e2.equals(e), if the graph contains such + * edge. Returns true if the graph contained the specified edge. + * (The graph will not contain the specified edge once the call returns). + * + *

If the specified edge is null returns + * false.

+ * + * @param e edge to be removed from this graph, if present. + * + * @return true if and only if the graph contained the + * specified edge. + */ + public boolean removeEdge(E e); + + /** + * Removes the specified vertex from this graph including all its touching + * edges if present. More formally, if the graph contains a vertex + * u such that u.equals(v), the call removes all edges + * that touch u and then removes u itself. If no + * such u is found, the call leaves the graph unchanged. + * Returns true if the graph contained the specified vertex. (The + * graph will not contain the specified vertex once the call returns). + * + *

If the specified vertex is null returns + * false.

+ * + * @param v vertex to be removed from this graph, if present. + * + * @return true if the graph contained the specified vertex; + * false otherwise. + */ + public boolean removeVertex(V v); + + /** + * Returns a set of the vertices contained in this graph. The set is backed + * by the graph, so changes to the graph are reflected in the set. If the + * graph is modified while an iteration over the set is in progress, the + * results of the iteration are undefined. + * + *

The graph implementation may maintain a particular set ordering (e.g. + * via {@link java.util.LinkedHashSet}) for deterministic iteration, but + * this is not required. It is the responsibility of callers who rely on + * this behavior to only use graph implementations which support it.

+ * + * @return a set view of the vertices contained in this graph. + */ + public Set vertexSet(); + + /** + * Returns the source vertex of an edge. For an undirected graph, source and + * target are distinguishable designations (but without any mathematical + * meaning). + * + * @param e edge of interest + * + * @return source vertex + */ + public V getEdgeSource(E e); + + /** + * Returns the target vertex of an edge. For an undirected graph, source and + * target are distinguishable designations (but without any mathematical + * meaning). + * + * @param e edge of interest + * + * @return target vertex + */ + public V getEdgeTarget(E e); + + /** + * Returns the weight assigned to a given edge. Unweighted graphs return 1.0 + * (as defined by {@link WeightedGraph#DEFAULT_EDGE_WEIGHT}), allowing + * weighted-graph algorithms to apply to them where meaningful. + * + * @param e edge of interest + * + * @return edge weight + * + * @see WeightedGraph + */ + public double getEdgeWeight(E e); +} + +// End Graph.java diff --git a/wdl/org/jgrapht/GraphHelper.java b/wdl/org/jgrapht/GraphHelper.java new file mode 100644 index 0000000..e45510a --- /dev/null +++ b/wdl/org/jgrapht/GraphHelper.java @@ -0,0 +1,59 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * GraphHelper.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * Mikael Hansen + * + * $Id$ + * + * Changes + * ------- + * 10-Jul-2003 : Initial revision (BN); + * 06-Nov-2003 : Change edge sharing semantics (JVS); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht; + +/** + * A collection of utilities to assist the working with graphs. + * + * @author Barak Naveh + * @since Jul 31, 2003 + * @deprecated Use {@link Graphs} instead. + */ +@Deprecated public abstract class GraphHelper + extends Graphs +{ +} + +// End GraphHelper.java diff --git a/wdl/org/jgrapht/GraphMapping.java b/wdl/org/jgrapht/GraphMapping.java new file mode 100644 index 0000000..1f70b58 --- /dev/null +++ b/wdl/org/jgrapht/GraphMapping.java @@ -0,0 +1,75 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * GraphMapping.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): John V. Sichi + * + * Changes + * ------- + */ +package org.jgrapht; + +/** + * GraphMapping represents a bidirectional mapping between two graphs (called + * graph1 and graph2), which allows the caller to obtain the matching vertex or + * edge in either direction, from graph1 to graph2, or from graph2 to graph1. It + * does not have to always be a complete bidirectional mapping (it could return + * null for some lookups). + * + * @author Assaf Lehr + * @since Jul 30, 2005 + */ +public interface GraphMapping +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Gets the mapped value where the key is vertex + * + * @param vertex vertex in one of the graphs + * @param forward if true, uses mapping from graph1 to graph2; if false, use + * mapping from graph2 to graph1 + * + * @return corresponding vertex in other graph, or null if none + */ + public V getVertexCorrespondence(V vertex, boolean forward); + + /** + * Gets the mapped value where the key is edge + * + * @param edge edge in one of the graphs + * @param forward if true, uses mapping from graph1 to graph2; if false, use + * mapping from graph2 to graph1 + * + * @return corresponding edge in other graph, or null if none + */ + public E getEdgeCorrespondence(E edge, boolean forward); +} + +// End GraphMapping.java diff --git a/wdl/org/jgrapht/GraphPath.java b/wdl/org/jgrapht/GraphPath.java new file mode 100644 index 0000000..c08e679 --- /dev/null +++ b/wdl/org/jgrapht/GraphPath.java @@ -0,0 +1,105 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------- + * Graph.java + * ---------- + * (C) Copyright 2008-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 1-Jan-2008 : Initial revision (JVS); + * + */ +package org.jgrapht; + +import java.util.*; + + +/** + * A GraphPath represents a + * path in a {@link Graph}. Note that a path is defined primarily in terms + * of edges (rather than vertices) so that multiple edges between the same pair + * of vertices can be discriminated. + * + * @author John Sichi + * @since Jan 1, 2008 + */ +public interface GraphPath +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the graph over which this path is defined. The path may also be + * valid with respect to other graphs. + * + * @return the containing graph + */ + public Graph getGraph(); + + /** + * Returns the start vertex in the path. + * + * @return the start vertex + */ + public V getStartVertex(); + + /** + * Returns the end vertex in the path. + * + * @return the end vertex + */ + public V getEndVertex(); + + /** + * Returns the edges making up the path. The first edge in this path is + * incident to the start vertex. The last edge is incident to the end + * vertex. The vertices along the path can be obtained by traversing from + * the start vertex, finding its opposite across the first edge, and then + * doing the same successively across subsequent edges; {@link + * Graphs#getPathVertexList} provides a convenience method for this. + * + *

Whether or not the returned edge list is modifiable depends on the + * path implementation. + * + * @return list of edges traversed by the path + */ + public List getEdgeList(); + + /** + * Returns the weight assigned to the path. Typically, this will be the sum + * of the weights of the edge list entries (as defined by the containing + * graph), but some path implementations may use other definitions. + * + * @return the weight of the path + */ + public double getWeight(); +} + +// End GraphPath.java diff --git a/wdl/org/jgrapht/Graphs.java b/wdl/org/jgrapht/Graphs.java new file mode 100644 index 0000000..0b2754b --- /dev/null +++ b/wdl/org/jgrapht/Graphs.java @@ -0,0 +1,442 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * Graphs.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * Mikael Hansen + * + * $Id$ + * + * Changes + * ------- + * 10-Jul-2003 : Initial revision (BN); + * 06-Nov-2003 : Change edge sharing semantics (JVS); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht; + +import java.util.*; + +import org.jgrapht.graph.*; + + +/** + * A collection of utilities to assist with graph manipulation. + * + * @author Barak Naveh + * @since Jul 31, 2003 + */ +public abstract class Graphs +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Creates a new edge and adds it to the specified graph similarly to the + * {@link Graph#addEdge(Object, Object)} method. + * + * @param g the graph for which the edge to be added. + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @param weight weight of the edge. + * + * @return The newly created edge if added to the graph, otherwise + * null. + * + * @see Graph#addEdge(Object, Object) + */ + public static E addEdge( + Graph g, + V sourceVertex, + V targetVertex, + double weight) + { + EdgeFactory ef = g.getEdgeFactory(); + E e = ef.createEdge(sourceVertex, targetVertex); + + // we first create the edge and set the weight to make sure that + // listeners will see the correct weight upon addEdge. + + assert (g instanceof WeightedGraph) : g.getClass(); + ((WeightedGraph) g).setEdgeWeight(e, weight); + + return g.addEdge(sourceVertex, targetVertex, e) ? e : null; + } + + /** + * Adds the specified source and target vertices to the graph, if not + * already included, and creates a new edge and adds it to the specified + * graph similarly to the {@link Graph#addEdge(Object, Object)} method. + * + * @param g the graph for which the specified edge to be added. + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * + * @return The newly created edge if added to the graph, otherwise + * null. + */ + public static E addEdgeWithVertices( + Graph g, + V sourceVertex, + V targetVertex) + { + g.addVertex(sourceVertex); + g.addVertex(targetVertex); + + return g.addEdge(sourceVertex, targetVertex); + } + + /** + * Adds the specified edge to the graph, including its vertices if not + * already included. + * + * @param targetGraph the graph for which the specified edge to be added. + * @param sourceGraph the graph in which the specified edge is already + * present + * @param edge edge to add + * + * @return true if the target graph did not already contain the + * specified edge. + */ + public static boolean addEdgeWithVertices( + Graph targetGraph, + Graph sourceGraph, + E edge) + { + V sourceVertex = sourceGraph.getEdgeSource(edge); + V targetVertex = sourceGraph.getEdgeTarget(edge); + + targetGraph.addVertex(sourceVertex); + targetGraph.addVertex(targetVertex); + + return targetGraph.addEdge(sourceVertex, targetVertex, edge); + } + + /** + * Adds the specified source and target vertices to the graph, if not + * already included, and creates a new weighted edge and adds it to the + * specified graph similarly to the {@link Graph#addEdge(Object, Object)} + * method. + * + * @param g the graph for which the specified edge to be added. + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @param weight weight of the edge. + * + * @return The newly created edge if added to the graph, otherwise + * null. + */ + public static E addEdgeWithVertices( + Graph g, + V sourceVertex, + V targetVertex, + double weight) + { + g.addVertex(sourceVertex); + g.addVertex(targetVertex); + + return addEdge(g, sourceVertex, targetVertex, weight); + } + + /** + * Adds all the vertices and all the edges of the specified source graph to + * the specified destination graph. First all vertices of the source graph + * are added to the destination graph. Then every edge of the source graph + * is added to the destination graph. This method returns true + * if the destination graph has been modified as a result of this operation, + * otherwise it returns false. + * + *

The behavior of this operation is undefined if any of the specified + * graphs is modified while operation is in progress.

+ * + * @param destination the graph to which vertices and edges are added. + * @param source the graph used as source for vertices and edges to add. + * + * @return true if and only if the destination graph has been + * changed as a result of this operation. + */ + public static boolean addGraph( + Graph destination, + Graph source) + { + boolean modified = addAllVertices(destination, source.vertexSet()); + modified |= addAllEdges(destination, source, source.edgeSet()); + + return modified; + } + + /** + * Adds all the vertices and all the edges of the specified source digraph + * to the specified destination digraph, reversing all of the edges. If you + * want to do this as a linked view of the source graph (rather than by + * copying to a destination graph), use {@link EdgeReversedGraph} instead. + * + *

The behavior of this operation is undefined if any of the specified + * graphs is modified while operation is in progress.

+ * + * @param destination the graph to which vertices and edges are added. + * @param source the graph used as source for vertices and edges to add. + * + * @see EdgeReversedGraph + */ + public static void addGraphReversed( + DirectedGraph destination, + DirectedGraph source) + { + addAllVertices(destination, source.vertexSet()); + + for (E edge : source.edgeSet()) { + destination.addEdge( + source.getEdgeTarget(edge), + source.getEdgeSource(edge)); + } + } + + /** + * Adds a subset of the edges of the specified source graph to the specified + * destination graph. The behavior of this operation is undefined if either + * of the graphs is modified while the operation is in progress. {@link + * #addEdgeWithVertices} is used for the transfer, so source vertexes will + * be added automatically to the target graph. + * + * @param destination the graph to which edges are to be added + * @param source the graph used as a source for edges to add + * @param edges the edges to be added + * + * @return true if this graph changed as a result of the call + */ + public static boolean addAllEdges( + Graph destination, + Graph source, + Collection edges) + { + boolean modified = false; + + for (E e : edges) { + V s = source.getEdgeSource(e); + V t = source.getEdgeTarget(e); + destination.addVertex(s); + destination.addVertex(t); + modified |= destination.addEdge(s, t, e); + } + + return modified; + } + + /** + * Adds all of the specified vertices to the destination graph. The behavior + * of this operation is undefined if the specified vertex collection is + * modified while the operation is in progress. This method will invoke the + * {@link Graph#addVertex(Object)} method. + * + * @param destination the graph to which edges are to be added + * @param vertices the vertices to be added to the graph. + * + * @return true if graph changed as a result of the call + * + * @throws NullPointerException if the specified vertices contains one or + * more null vertices, or if the specified vertex collection is + * null. + * + * @see Graph#addVertex(Object) + */ + public static boolean addAllVertices( + Graph destination, + Collection vertices) + { + boolean modified = false; + + for (V v : vertices) { + modified |= destination.addVertex(v); + } + + return modified; + } + + /** + * Returns a list of vertices that are the neighbors of a specified vertex. + * If the graph is a multigraph vertices may appear more than once in the + * returned list. + * + * @param g the graph to look for neighbors in. + * @param vertex the vertex to get the neighbors of. + * + * @return a list of the vertices that are the neighbors of the specified + * vertex. + */ + public static List neighborListOf(Graph g, + V vertex) + { + List neighbors = new ArrayList(); + + for (E e : g.edgesOf(vertex)) { + neighbors.add(getOppositeVertex(g, e, vertex)); + } + + return neighbors; + } + + /** + * Returns a list of vertices that are the direct predecessors of a + * specified vertex. If the graph is a multigraph, vertices may appear more + * than once in the returned list. + * + * @param g the graph to look for predecessors in. + * @param vertex the vertex to get the predecessors of. + * + * @return a list of the vertices that are the direct predecessors of the + * specified vertex. + */ + public static List predecessorListOf( + DirectedGraph g, + V vertex) + { + List predecessors = new ArrayList(); + Set edges = g.incomingEdgesOf(vertex); + + for (E e : edges) { + predecessors.add(getOppositeVertex(g, e, vertex)); + } + + return predecessors; + } + + /** + * Returns a list of vertices that are the direct successors of a specified + * vertex. If the graph is a multigraph vertices may appear more than once + * in the returned list. + * + * @param g the graph to look for successors in. + * @param vertex the vertex to get the successors of. + * + * @return a list of the vertices that are the direct successors of the + * specified vertex. + */ + public static List successorListOf( + DirectedGraph g, + V vertex) + { + List successors = new ArrayList(); + Set edges = g.outgoingEdgesOf(vertex); + + for (E e : edges) { + successors.add(getOppositeVertex(g, e, vertex)); + } + + return successors; + } + + /** + * Returns an undirected view of the specified graph. If the specified graph + * is directed, returns an undirected view of it. If the specified graph is + * already undirected, just returns it. + * + * @param g the graph for which an undirected view is to be returned. + * + * @return an undirected view of the specified graph, if it is directed, or + * or the specified graph itself if it is already undirected. + * + * @throws IllegalArgumentException if the graph is neither DirectedGraph + * nor UndirectedGraph. + * + * @see AsUndirectedGraph + */ + public static UndirectedGraph undirectedGraph(Graph g) + { + if (g instanceof DirectedGraph) { + return new AsUndirectedGraph((DirectedGraph) g); + } else if (g instanceof UndirectedGraph) { + return (UndirectedGraph) g; + } else { + throw new IllegalArgumentException( + "Graph must be either DirectedGraph or UndirectedGraph"); + } + } + + /** + * Tests whether an edge is incident to a vertex. + * + * @param g graph containing e and v + * @param e edge in g + * @param v vertex in g + * + * @return true iff e is incident on v + */ + public static boolean testIncidence(Graph g, E e, V v) + { + return (g.getEdgeSource(e).equals(v)) + || (g.getEdgeTarget(e).equals(v)); + } + + /** + * Gets the vertex opposite another vertex across an edge. + * + * @param g graph containing e and v + * @param e edge in g + * @param v vertex in g + * + * @return vertex opposite to v across e + */ + public static V getOppositeVertex(Graph g, E e, V v) + { + V source = g.getEdgeSource(e); + V target = g.getEdgeTarget(e); + if (v.equals(source)) { + return target; + } else if (v.equals(target)) { + return source; + } else { + throw new IllegalArgumentException("no such vertex"); + } + } + + /** + * Gets the list of vertices visited by a path. + * + * @param path path of interest + * + * @return corresponding vertex list + */ + public static List getPathVertexList(GraphPath path) + { + Graph g = path.getGraph(); + List list = new ArrayList(); + V v = path.getStartVertex(); + list.add(v); + for (E e : path.getEdgeList()) { + v = getOppositeVertex(g, e, v); + list.add(v); + } + return list; + } +} + +// End Graphs.java diff --git a/wdl/org/jgrapht/ListenableGraph.java b/wdl/org/jgrapht/ListenableGraph.java new file mode 100644 index 0000000..7cba50d --- /dev/null +++ b/wdl/org/jgrapht/ListenableGraph.java @@ -0,0 +1,90 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------- + * ListenableGraph.java + * -------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht; + +import org.jgrapht.event.*; + + +/** + * A graph that supports listeners on structural change events. + * + * @author Barak Naveh + * @see GraphListener + * @see VertexSetListener + * @since Jul 20, 2003 + */ +public interface ListenableGraph + extends Graph +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Adds the specified graph listener to this graph, if not already present. + * + * @param l the listener to be added. + */ + public void addGraphListener(GraphListener l); + + /** + * Adds the specified vertex set listener to this graph, if not already + * present. + * + * @param l the listener to be added. + */ + public void addVertexSetListener(VertexSetListener l); + + /** + * Removes the specified graph listener from this graph, if present. + * + * @param l the listener to be removed. + */ + public void removeGraphListener(GraphListener l); + + /** + * Removes the specified vertex set listener from this graph, if present. + * + * @param l the listener to be removed. + */ + public void removeVertexSetListener(VertexSetListener l); +} + +// End ListenableGraph.java diff --git a/wdl/org/jgrapht/UndirectedGraph.java b/wdl/org/jgrapht/UndirectedGraph.java new file mode 100644 index 0000000..6429f16 --- /dev/null +++ b/wdl/org/jgrapht/UndirectedGraph.java @@ -0,0 +1,70 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------- + * UndirectedGraph.java + * -------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht; + +/** + * A graph whose all edges are undirected. This is the root interface of all + * undirected graphs. + * + *

See + * http://mathworld.wolfram.com/Graph.html for more on undirected and on + * directed graphs.

+ * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public interface UndirectedGraph + extends Graph +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the degree of the specified vertex. A degree of a vertex in an + * undirected graph is the number of edges touching that vertex. + * + * @param vertex vertex whose degree is to be calculated. + * + * @return the degree of the specified vertex. + */ + public int degreeOf(V vertex); +} + +// End UndirectedGraph.java diff --git a/wdl/org/jgrapht/VertexFactory.java b/wdl/org/jgrapht/VertexFactory.java new file mode 100644 index 0000000..86e8551 --- /dev/null +++ b/wdl/org/jgrapht/VertexFactory.java @@ -0,0 +1,63 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * VertexFactory.java + * ------------------ + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht; + +/** + * A vertex factory used by graph algorithms for creating new vertices. + * Normally, vertices are constructed by user code and added to a graph + * explicitly, but algorithms which generate new vertices require a factory. + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public interface VertexFactory +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Creates a new vertex. + * + * @return the new vertex + */ + public V createVertex(); +} + +// End VertexFactory.java diff --git a/wdl/org/jgrapht/WeightedGraph.java b/wdl/org/jgrapht/WeightedGraph.java new file mode 100644 index 0000000..0d29745 --- /dev/null +++ b/wdl/org/jgrapht/WeightedGraph.java @@ -0,0 +1,71 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * WeightedGraph.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 13-Aug-2003 : Included weight methods in Edge interface (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht; + +/** + * An interface for a graph whose edges have non-uniform weights. + * + * @author Barak Naveh + * @since Jul 23, 2003 + */ +public interface WeightedGraph + extends Graph +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * The default weight for an edge. + */ + public static double DEFAULT_EDGE_WEIGHT = 1.0; + + //~ Methods ---------------------------------------------------------------- + + /** + * Assigns a weight to an edge. + * + * @param e edge on which to set weight + * @param weight new weight for edge + */ + public void setEdgeWeight(E e, double weight); +} + +// End WeightedGraph.java diff --git a/wdl/org/jgrapht/alg/AbstractPathElement.java b/wdl/org/jgrapht/alg/AbstractPathElement.java new file mode 100644 index 0000000..5999888 --- /dev/null +++ b/wdl/org/jgrapht/alg/AbstractPathElement.java @@ -0,0 +1,202 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * AbstractPathElement.java + * ------------------------- + * (C) Copyright 2006-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jan-2006 : Initial revision (GB); + * 14-Jan-2006 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * A new path is created from a path concatenated to an edge. It's like a linked + * list.
+ * The empty path is composed only of one vertex.
+ * In this case the path has no previous path element.
+ * . + * + *

NOTE jvs 1-Jan-2008: This is an internal data structure for use in + * algorithms. For returning paths to callers, use the public {@link GraphPath} + * interface instead. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +abstract class AbstractPathElement +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Number of hops of the path. + */ + protected int nHops; + + /** + * Edge reaching the target vertex of the path. + */ + protected E prevEdge; + + /** + * Previous path element. + */ + protected AbstractPathElement prevPathElement; + + /** + * Target vertex. + */ + private V vertex; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a path element by concatenation of an edge to a path element. + * + * @param pathElement + * @param edge edge reaching the end vertex of the path element created. + */ + protected AbstractPathElement( + Graph graph, + AbstractPathElement pathElement, + E edge) + { + this.vertex = + Graphs.getOppositeVertex( + graph, + edge, + pathElement.getVertex()); + this.prevEdge = edge; + this.prevPathElement = pathElement; + + this.nHops = pathElement.getHopCount() + 1; + } + + /** + * Copy constructor. + * + * @param original source to copy from + */ + protected AbstractPathElement(AbstractPathElement original) + { + this.nHops = original.nHops; + this.prevEdge = original.prevEdge; + this.prevPathElement = original.prevPathElement; + this.vertex = original.vertex; + } + + /** + * Creates an empty path element. + * + * @param vertex end vertex of the path element. + */ + protected AbstractPathElement(V vertex) + { + this.vertex = vertex; + this.prevEdge = null; + this.prevPathElement = null; + + this.nHops = 0; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the path as a list of edges. + * + * @return list of Edge. + */ + public List createEdgeListPath() + { + List path = new ArrayList(); + AbstractPathElement pathElement = this; + + // while start vertex is not reached. + while (pathElement.getPrevEdge() != null) { + path.add(pathElement.getPrevEdge()); + + pathElement = pathElement.getPrevPathElement(); + } + + Collections.reverse(path); + + return path; + } + + /** + * Returns the number of hops (or number of edges) of the path. + * + * @return . + */ + public int getHopCount() + { + return this.nHops; + } + + /** + * Returns the edge reaching the target vertex of the path. + * + * @return null if the path is empty. + */ + public E getPrevEdge() + { + return this.prevEdge; + } + + /** + * Returns the previous path element. + * + * @return null is the path is empty. + */ + public AbstractPathElement getPrevPathElement() + { + return this.prevPathElement; + } + + /** + * Returns the target vertex of the path. + * + * @return . + */ + public V getVertex() + { + return this.vertex; + } +} + +// End AbstractPathElement.java diff --git a/wdl/org/jgrapht/alg/AbstractPathElementList.java b/wdl/org/jgrapht/alg/AbstractPathElementList.java new file mode 100644 index 0000000..a81082b --- /dev/null +++ b/wdl/org/jgrapht/alg/AbstractPathElementList.java @@ -0,0 +1,196 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * AbstractPathElementList.java + * ------------------------- + * (C) Copyright 2007-2010, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * 06-Dec-2010 : Bugfixes (GB); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * List of paths AbstractPathElement with same target vertex. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +abstract class AbstractPathElementList> + extends AbstractList +{ + //~ Instance fields -------------------------------------------------------- + + protected Graph graph; + + /** + * Max number of stored paths. + */ + protected int maxSize; + + /** + * Stored paths, list of AbstractPathElement. + */ + protected ArrayList pathElements = new ArrayList(); + + /** + * Target vertex of the paths. + */ + protected V vertex; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates paths obtained by concatenating the specified edge to the + * specified paths. + * + * @param maxSize maximum number of paths the list is able to store. + * @param elementList paths, list of AbstractPathElement. + * @param edge edge reaching the end vertex of the created paths. + * + * @throws NullPointerException if the specified prevPathElementList or edge + * is null. + * @throws IllegalArgumentException if maxSize is negative or + * 0. + */ + protected AbstractPathElementList( + Graph graph, + int maxSize, + AbstractPathElementList elementList, + E edge) + { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize is negative or 0"); + } + if (elementList == null) { + throw new NullPointerException("elementList is null"); + } + if (edge == null) { + throw new NullPointerException("edge is null"); + } + + this.graph = graph; + this.maxSize = maxSize; + this.vertex = + Graphs.getOppositeVertex(graph, edge, elementList.getVertex()); + } + + /** + * Creates a list with an empty path. The list size is 1. + * + * @param maxSize maximum number of paths the list is able to store. + * + * @throws NullPointerException if the specified path-element is + * null. + * @throws IllegalArgumentException if maxSize is negative or + * 0. + * @throws IllegalArgumentException if pathElement is not + * empty. + */ + protected AbstractPathElementList( + Graph graph, + int maxSize, + T pathElement) + { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize is negative or 0"); + } + if (pathElement == null) { + throw new NullPointerException("pathElement is null"); + } + if (pathElement.getPrevEdge() != null) { + throw new IllegalArgumentException("path must be empty"); + } + + this.graph = graph; + this.maxSize = maxSize; + this.vertex = pathElement.getVertex(); + + this.pathElements.add(pathElement); + } + + /** + * Creates an empty list. The list size is 0. + * + * @param maxSize maximum number of paths the list is able to store. + * + * @throws IllegalArgumentException if maxSize is negative or + * 0. + */ + protected AbstractPathElementList(Graph graph, int maxSize, V vertex) + { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize is negative or 0"); + } + + this.graph = graph; + this.maxSize = maxSize; + this.vertex = vertex; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns path AbstractPathElement stored at the specified + * index. + */ + public T get(int index) + { + return this.pathElements.get(index); + } + + /** + * Returns target vertex. + */ + public V getVertex() + { + return this.vertex; + } + + /** + * Returns the number of paths stored in the list. + */ + public int size() + { + return this.pathElements.size(); + } +} + +// End AbstractPathElementList.java diff --git a/wdl/org/jgrapht/alg/BellmanFordIterator.java b/wdl/org/jgrapht/alg/BellmanFordIterator.java new file mode 100644 index 0000000..680add2 --- /dev/null +++ b/wdl/org/jgrapht/alg/BellmanFordIterator.java @@ -0,0 +1,448 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BellmanFordIterator.java + * ------------------------- + * (C) Copyright 2006-2008, by France Telecom and Contributors. + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jan-2006 : Initial revision (GB); + * 14-Jan-2006 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Helper class for {@link BellmanFordShortestPath}; not intended for general + * use. + */ +class BellmanFordIterator + implements Iterator> +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Error message. + */ + protected final static String NEGATIVE_UNDIRECTED_EDGE = + "Negative" + + "edge-weights are not allowed in an unidrected graph!"; + + //~ Instance fields -------------------------------------------------------- + + /** + * Graph on which shortest paths are searched. + */ + protected Graph graph; + + /** + * Start vertex. + */ + protected V startVertex; + + /** + * Vertices whose shortest path cost have been improved during the previous + * pass. + */ + private List prevImprovedVertices = new ArrayList(); + + private Map> prevVertexData; + + private boolean startVertexEncountered = false; + + /** + * Stores the vertices that have been seen during iteration and (optionally) + * some additional traversal info regarding each vertex. + */ + private Map> vertexData; + + private double epsilon; + + //~ Constructors ----------------------------------------------------------- + + /** + * @param graph + * @param startVertex start vertex. + * @param epsilon tolerance factor. + */ + protected BellmanFordIterator( + Graph graph, + V startVertex, + double epsilon) + { + assertBellmanFordIterator(graph, startVertex); + + this.graph = graph; + this.startVertex = startVertex; + this.epsilon = epsilon; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the path element of the shortest path with less than + * nMaxHops edges between the start vertex and the end vertex. + * + * @param endVertex end vertex. + * + * @return . + */ + public BellmanFordPathElement getPathElement(V endVertex) + { + return getSeenData(endVertex); + } + + /** + * @return true if at least one path has been improved during + * the previous pass, false otherwise. + */ + public boolean hasNext() + { + if (!this.startVertexEncountered) { + encounterStartVertex(); + } + + return !(this.prevImprovedVertices.isEmpty()); + } + + /** + * Returns the list Collection of vertices whose path has been + * improved during the current pass. + * + * @see java.util.Iterator#next() + */ + public List next() + { + if (!this.startVertexEncountered) { + encounterStartVertex(); + } + + if (hasNext()) { + List improvedVertices = new ArrayList(); + for (int i = this.prevImprovedVertices.size() - 1; i >= 0; i--) { + V vertex = this.prevImprovedVertices.get(i); + for ( + Iterator iter = edgesOfIterator(vertex); + iter.hasNext();) + { + E edge = iter.next(); + V oppositeVertex = + Graphs.getOppositeVertex( + graph, + edge, + vertex); + if (getPathElement(oppositeVertex) != null) { + boolean relaxed = + relaxVertexAgain(oppositeVertex, edge); + if (relaxed) { + improvedVertices.add(oppositeVertex); + } + } else { + relaxVertex(oppositeVertex, edge); + improvedVertices.add(oppositeVertex); + } + } + } + + savePassData(improvedVertices); + + return improvedVertices; + } + + throw new NoSuchElementException(); + } + + /** + * Unsupported + * + * @see java.util.Iterator#remove() + */ + public void remove() + { + throw new UnsupportedOperationException(); + } + + /** + * @param edge + * + * @throws IllegalArgumentException if the graph is undirected and the + * edge-weight is negative. + */ + protected void assertValidEdge(E edge) + { + if (this.graph instanceof UndirectedGraph) { + if (graph.getEdgeWeight(edge) < 0) { + throw new IllegalArgumentException(NEGATIVE_UNDIRECTED_EDGE); + } + } + } + + /** + * Costs taken into account are the weights stored in Edge + * objects. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + * + * @return the cost obtained by concatenation. + * + * @see Graph#getEdgeWeight(E) + */ + protected double calculatePathCost(V vertex, E edge) + { + V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex); + + // we get the data of the previous pass. + BellmanFordPathElement oppositePrevData = + getPrevSeenData(oppositeVertex); + + double pathCost = graph.getEdgeWeight(edge); + + if (!oppositePrevData.getVertex().equals(this.startVertex)) { + // if it's not the start vertex, we add the cost of the previous + // pass. + pathCost += oppositePrevData.getCost(); + } + + return pathCost; + } + + /** + * Returns an iterator to loop over outgoing edges Edge of the + * vertex. + * + * @param vertex + * + * @return . + */ + protected Iterator edgesOfIterator(V vertex) + { + if (this.graph instanceof DirectedGraph) { + return ((DirectedGraph) this.graph).outgoingEdgesOf(vertex) + .iterator(); + } else { + return this.graph.edgesOf(vertex).iterator(); + } + } + + /** + * Access the data stored for a seen vertex in the previous pass. + * + * @param vertex a vertex which has already been seen. + * + * @return data associated with the seen vertex or null if no + * data was associated with the vertex. + */ + protected BellmanFordPathElement getPrevSeenData(V vertex) + { + return this.prevVertexData.get(vertex); + } + + /** + * Access the data stored for a seen vertex in the current pass. + * + * @param vertex a vertex which has already been seen. + * + * @return data associated with the seen vertex or null if no + * data was associated with the vertex. + */ + protected BellmanFordPathElement getSeenData(V vertex) + { + return this.vertexData.get(vertex); + } + + /** + * Determines whether a vertex has been seen yet by this traversal. + * + * @param vertex vertex in question. + * + * @return true if vertex has already been seen. + */ + protected boolean isSeenVertex(V vertex) + { + return this.vertexData.containsKey(vertex); + } + + /** + * @param vertex + * @param data + * + * @return . + */ + protected BellmanFordPathElement putPrevSeenData( + V vertex, + BellmanFordPathElement data) + { + if (this.prevVertexData == null) { + this.prevVertexData = + new HashMap>(); + } + + return this.prevVertexData.put(vertex, data); + } + + /** + * Stores iterator-dependent data for a vertex that has been seen during the + * current pass. + * + * @param vertex a vertex which has been seen. + * @param data data to be associated with the seen vertex. + * + * @return previous value associated with specified vertex or + * null if no data was associated with the vertex. + */ + protected BellmanFordPathElement putSeenData( + V vertex, + BellmanFordPathElement data) + { + if (this.vertexData == null) { + this.vertexData = new HashMap>(); + } + + return this.vertexData.put(vertex, data); + } + + private void assertBellmanFordIterator(Graph graph, V startVertex) + { + if (!(graph.containsVertex(startVertex))) { + throw new IllegalArgumentException( + "Graph must contain the start vertex!"); + } + } + + /** + * The first time we see a vertex, make up a new entry for it. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + * @param cost cost of the created path element. + * + * @return the new entry. + */ + private BellmanFordPathElement createSeenData( + V vertex, + E edge, + double cost) + { + BellmanFordPathElement prevPathElement = + getPrevSeenData( + Graphs.getOppositeVertex(graph, edge, vertex)); + + BellmanFordPathElement data = + new BellmanFordPathElement( + graph, + prevPathElement, + edge, + cost, + epsilon); + + return data; + } + + private void encounterStartVertex() + { + BellmanFordPathElement data = + new BellmanFordPathElement( + this.startVertex, + epsilon); + + // first the only vertex considered as improved is the start vertex. + this.prevImprovedVertices.add(this.startVertex); + + putSeenData(this.startVertex, data); + putPrevSeenData(this.startVertex, data); + + this.startVertexEncountered = true; + } + + /** + * Upates data first time a vertex is reached by a path. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + */ + private void relaxVertex(V vertex, E edge) + { + assertValidEdge(edge); + + double shortestPathCost = calculatePathCost(vertex, edge); + + BellmanFordPathElement data = + createSeenData(vertex, edge, + shortestPathCost); + + putSeenData(vertex, data); + } + + /** + * Check if the cost of the best path so far reaching the specified vertex + * could be improved if the vertex is reached through the specified edge. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + * + * @return true if the cost has been improved, + * false otherwise. + */ + private boolean relaxVertexAgain(V vertex, E edge) + { + assertValidEdge(edge); + + double candidateCost = calculatePathCost(vertex, edge); + + // we get the data of the previous pass. + BellmanFordPathElement oppositePrevData = + getPrevSeenData( + Graphs.getOppositeVertex(graph, edge, vertex)); + + BellmanFordPathElement pathElement = getSeenData(vertex); + return pathElement.improve(oppositePrevData, edge, candidateCost); + } + + private void savePassData(List improvedVertices) + { + for (V vertex : improvedVertices) { + BellmanFordPathElement orig = getSeenData(vertex); + BellmanFordPathElement clonedData = + new BellmanFordPathElement(orig); + putPrevSeenData(vertex, clonedData); + } + + this.prevImprovedVertices = improvedVertices; + } +} + +// End BellmanFordIterator.java diff --git a/wdl/org/jgrapht/alg/BellmanFordPathElement.java b/wdl/org/jgrapht/alg/BellmanFordPathElement.java new file mode 100644 index 0000000..8b88264 --- /dev/null +++ b/wdl/org/jgrapht/alg/BellmanFordPathElement.java @@ -0,0 +1,150 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BellmanFordPathElement.java + * ------------------------- + * (C) Copyright 2006-2008, by France Telecom and Contributors. + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jan-2006 : Initial revision (GB); + * 14-Jan-2006 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import org.jgrapht.*; + + +/** + * Helper class for {@link BellmanFordShortestPath}; not intended for general + * use. + */ +final class BellmanFordPathElement + extends AbstractPathElement +{ + //~ Instance fields -------------------------------------------------------- + + private double cost = 0; + private double epsilon; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a path element by concatenation of an edge to a path element. + * + * @param pathElement + * @param edge edge reaching the end vertex of the path element created. + * @param cost total cost of the created path element. + * @param epsilon tolerance factor. + */ + protected BellmanFordPathElement( + Graph graph, + BellmanFordPathElement pathElement, + E edge, + double cost, + double epsilon) + { + super(graph, pathElement, edge); + + this.cost = cost; + this.epsilon = epsilon; + } + + /** + * Copy constructor. + * + * @param original source to copy from + */ + BellmanFordPathElement(BellmanFordPathElement original) + { + super(original); + this.cost = original.cost; + this.epsilon = original.epsilon; + } + + /** + * Creates an empty path element. + * + * @param vertex end vertex of the path element. + * @param epsilon tolerance factor. + */ + protected BellmanFordPathElement(V vertex, double epsilon) + { + super(vertex); + + this.cost = 0; + this.epsilon = epsilon; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the total cost of the path element. + * + * @return . + */ + public double getCost() + { + return this.cost; + } + + /** + * Returns true if the path has been improved, + * false otherwise. We use an "epsilon" precision to check whether + * the cost has been improved (because of many roundings, a formula equal to + * 0 could unfortunately be evaluated to 10^-14). + * + * @param candidatePrevPathElement + * @param candidateEdge + * @param candidateCost + * + * @return . + */ + protected boolean improve( + BellmanFordPathElement candidatePrevPathElement, + E candidateEdge, + double candidateCost) + { + // to avoid improvement only due to rounding errors. + if (candidateCost < (getCost() - epsilon)) { + this.prevPathElement = candidatePrevPathElement; + this.prevEdge = candidateEdge; + this.cost = candidateCost; + this.nHops = candidatePrevPathElement.getHopCount() + 1; + + return true; + } else { + return false; + } + } +} + +// End BellmanFordPathElement.java diff --git a/wdl/org/jgrapht/alg/BellmanFordShortestPath.java b/wdl/org/jgrapht/alg/BellmanFordShortestPath.java new file mode 100644 index 0000000..dcce9ff --- /dev/null +++ b/wdl/org/jgrapht/alg/BellmanFordShortestPath.java @@ -0,0 +1,239 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BellmanFordShortestPath.java + * ------------------------- + * (C) Copyright 2006-2008, by France Telecom and Contributors. + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jan-2006 : Initial revision (GB); + * 14-Jan-2006 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Bellman-Ford + * algorithm: weights could be negative, paths could be constrained by a + * maximum number of edges. + */ +public class BellmanFordShortestPath +{ + //~ Static fields/initializers --------------------------------------------- + + private static final double DEFAULT_EPSILON = 0.000000001; + + //~ Instance fields -------------------------------------------------------- + + /** + * Graph on which shortest paths are searched. + */ + protected Graph graph; + + /** + * Start vertex. + */ + protected V startVertex; + + private BellmanFordIterator iter; + + /** + * Maximum number of edges of the calculated paths. + */ + private int nMaxHops; + + private int passNumber; + + private double epsilon; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates an object to calculate shortest paths between the start vertex + * and others vertices using the Bellman-Ford algorithm. + * + * @param graph + * @param startVertex + */ + public BellmanFordShortestPath(Graph graph, V startVertex) + { + this(graph, startVertex, graph.vertexSet().size() - 1); + } + + /** + * Creates an object to calculate shortest paths between the start vertex + * and others vertices using the Bellman-Ford algorithm. + * + * @param graph + * @param startVertex + * @param nMaxHops maximum number of edges of the calculated paths. + */ + public BellmanFordShortestPath( + Graph graph, + V startVertex, + int nMaxHops) + { + this(graph, startVertex, nMaxHops, DEFAULT_EPSILON); + } + + /** + * Creates an object to calculate shortest paths between the start vertex + * and others vertices using the Bellman-Ford algorithm. + * + * @param graph + * @param startVertex + * @param nMaxHops maximum number of edges of the calculated paths. + * @param epsilon tolerance factor. + */ + public BellmanFordShortestPath( + Graph graph, + V startVertex, + int nMaxHops, + double epsilon) + { + this.startVertex = startVertex; + this.nMaxHops = nMaxHops; + this.graph = graph; + this.passNumber = 1; + this.epsilon = epsilon; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @param endVertex end vertex. + * + * @return the cost of the shortest path between the start vertex and the + * end vertex. + */ + public double getCost(V endVertex) + { + assertGetPath(endVertex); + + lazyCalculate(); + + BellmanFordPathElement pathElement = + this.iter.getPathElement(endVertex); + + if (pathElement == null) { + return Double.POSITIVE_INFINITY; + } + + return pathElement.getCost(); + } + + /** + * @param endVertex end vertex. + * + * @return list of Edge, or null if no path exists between the + * start vertex and the end vertex. + */ + public List getPathEdgeList(V endVertex) + { + assertGetPath(endVertex); + + lazyCalculate(); + + BellmanFordPathElement pathElement = + this.iter.getPathElement(endVertex); + + if (pathElement == null) { + return null; + } + + return pathElement.createEdgeListPath(); + } + + private void assertGetPath(V endVertex) + { + if (endVertex.equals(this.startVertex)) { + throw new IllegalArgumentException( + "The end vertex is the same as the start vertex!"); + } + + if (!this.graph.containsVertex(endVertex)) { + throw new IllegalArgumentException( + "Graph must contain the end vertex!"); + } + } + + private void lazyCalculate() + { + if (this.iter == null) { + this.iter = + new BellmanFordIterator( + this.graph, + this.startVertex, + epsilon); + } + + // at the i-th pass the shortest paths with less (or equal) than i edges + // are calculated. + for ( + ; + (this.passNumber <= this.nMaxHops) && this.iter.hasNext(); + this.passNumber++) + { + this.iter.next(); + } + } + + /** + * Convenience method to find the shortest path via a single static method + * call. If you need a more advanced search (e.g. limited by hops, or + * computation of the path length), use the constructor instead. + * + * @param graph the graph to be searched + * @param startVertex the vertex at which the path should start + * @param endVertex the vertex at which the path should end + * + * @return List of Edges, or null if no path exists + */ + public static List findPathBetween( + Graph graph, + V startVertex, + V endVertex) + { + BellmanFordShortestPath alg = + new BellmanFordShortestPath( + graph, + startVertex); + + return alg.getPathEdgeList(endVertex); + } +} + +// End BellmanFordShortestPath.java diff --git a/wdl/org/jgrapht/alg/BiconnectivityInspector.java b/wdl/org/jgrapht/alg/BiconnectivityInspector.java new file mode 100644 index 0000000..3e1c1ca --- /dev/null +++ b/wdl/org/jgrapht/alg/BiconnectivityInspector.java @@ -0,0 +1,138 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BiconnectivityInspector.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Inspects a graph for the biconnectivity property. See {@link + * BlockCutpointGraph} for more information. A biconnected graph has only one + * block (i.e. no cutpoints). + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class BiconnectivityInspector +{ + //~ Instance fields -------------------------------------------------------- + + private BlockCutpointGraph blockCutpointGraph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Running time = O(m) where m is the number of edges. + */ + public BiconnectivityInspector(UndirectedGraph graph) + { + super(); + this.blockCutpointGraph = new BlockCutpointGraph(graph); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the biconnected vertex-components of the graph. + */ + public Set> getBiconnectedVertexComponents() + { + Set> biconnectedVertexComponents = new HashSet>(); + for ( + Iterator> iter = + this.blockCutpointGraph.vertexSet().iterator(); + iter.hasNext();) + { + UndirectedGraph subgraph = iter.next(); + if (!subgraph.edgeSet().isEmpty()) { + biconnectedVertexComponents.add(subgraph.vertexSet()); + } + } + + return biconnectedVertexComponents; + } + + /** + * Returns the biconnected vertex-components containing the vertex. A + * biconnected vertex-component contains all the vertices in the component. + * A vertex which is not a cutpoint is contained in exactly one component. A + * cutpoint is contained is at least 2 components. + * + * @param vertex + * + * @return set of all biconnected vertex-components containing the vertex. + */ + public Set> getBiconnectedVertexComponents(V vertex) + { + Set> vertexComponents = new HashSet>(); + for ( + Iterator> iter = getBiconnectedVertexComponents().iterator(); + iter.hasNext();) + { + Set vertexComponent = iter.next(); + if (vertexComponent.contains(vertex)) { + vertexComponents.add(vertexComponent); + } + } + return vertexComponents; + } + + /** + * Returns the cutpoints of the graph. + */ + public Set getCutpoints() + { + return this.blockCutpointGraph.getCutpoints(); + } + + /** + * Returns true if the graph is biconnected (no cutpoint), + * false otherwise. + */ + public boolean isBiconnected() + { + return this.blockCutpointGraph.vertexSet().size() == 1; + } +} + +// End BiconnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/BlockCutpointGraph.java b/wdl/org/jgrapht/alg/BlockCutpointGraph.java new file mode 100644 index 0000000..5ea029c --- /dev/null +++ b/wdl/org/jgrapht/alg/BlockCutpointGraph.java @@ -0,0 +1,365 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BlockCutpointGraph.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + * Definition of a block of a + * graph in MathWorld.
+ *
Definition and lemma taken from the article + * Structure-Based Resilience Metrics for Service-Oriented Networks: + * + *

    + *
  • Definition 4.5 Let G(V; E) be a connected undirected graph. The + * block-cut point graph (BC graph) of G, denoted by GB(VB; EB), is the + * bipartite graph defined as follows. (a) VB has one node corresponding to each + * block and one node corresponding to each cut point of G. (b) Each edge fx; yg + * in EB joins a block node x to a cut point y if the block corresponding to x + * contains the cut point node corresponding to y.
  • + *
  • Lemma 4.4 Let G(V; E) be a connected undirected graph. (a) Each + * pair of blocks of G share at most one node, and that node is a cutpoint. (b) + * The BC graph of G is a tree in which each leaf node corresponds to a block of + * G.
  • + *
+ * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class BlockCutpointGraph + extends SimpleGraph, DefaultEdge> +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = -9101341117013163934L; + + //~ Instance fields -------------------------------------------------------- + + private Set cutpoints = new HashSet(); + + /** + * DFS (Depth-First-Search) tree. + */ + private DirectedGraph dfsTree; + + private UndirectedGraph graph; + + private int numOrder; + + private Deque stack = new ArrayDeque(); + + private Map>> vertex2biconnectedSubgraphs = + new HashMap>>(); + + private Map> vertex2block = + new HashMap>(); + + private Map vertex2numOrder = new HashMap(); + + //~ Constructors ----------------------------------------------------------- + + /** + * Running time = O(m) where m is the number of edges. + */ + public BlockCutpointGraph(UndirectedGraph graph) + { + super(DefaultEdge.class); + this.graph = graph; + + this.dfsTree = + new SimpleDirectedGraph( + DefaultEdge.class); + V s = graph.vertexSet().iterator().next(); + this.dfsTree.addVertex(s); + dfsVisit(s, s); + + if (this.dfsTree.edgesOf(s).size() > 1) { + this.cutpoints.add(s); + } else { + this.cutpoints.remove(s); + } + + for (Iterator iter = this.cutpoints.iterator(); iter.hasNext();) { + V cutpoint = iter.next(); + UndirectedGraph subgraph = + new SimpleGraph(this.graph.getEdgeFactory()); + subgraph.addVertex(cutpoint); + this.vertex2block.put(cutpoint, subgraph); + addVertex(subgraph); + Set> biconnectedSubgraphs = + getBiconnectedSubgraphs(cutpoint); + for ( + Iterator> iterator = + biconnectedSubgraphs.iterator(); + iterator.hasNext();) + { + UndirectedGraph biconnectedSubgraph = iterator.next(); + assert (vertexSet().contains(biconnectedSubgraph)); + addEdge(subgraph, biconnectedSubgraph); + } + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the vertex if vertex is a cutpoint, and otherwise returns the + * block (biconnected component) containing the vertex. + * + * @param vertex vertex in the initial graph. + */ + public UndirectedGraph getBlock(V vertex) + { + if (!this.graph.vertexSet().contains(vertex)) { + throw new IllegalArgumentException("No such vertex in the graph!"); + } + + return this.vertex2block.get(vertex); + } + + /** + * Returns the cutpoints of the initial graph. + */ + public Set getCutpoints() + { + return this.cutpoints; + } + + /** + * Returns true if the vertex is a cutpoint, false + * otherwise. + * + * @param vertex vertex in the initial graph. + */ + public boolean isCutpoint(V vertex) + { + if (!this.graph.vertexSet().contains(vertex)) { + throw new IllegalArgumentException("No such vertex in the graph!"); + } + + return this.cutpoints.contains(vertex); + } + + private void biconnectedComponentFinished(V s, V n) + { + this.cutpoints.add(s); + + Set vertexComponent = new HashSet(); + Set edgeComponent = new HashSet(); + BCGEdge edge = this.stack.removeLast(); + while ( + (getNumOrder(edge.getSource()) >= getNumOrder(n)) + && !this.stack.isEmpty()) + { + edgeComponent.add(edge); + + vertexComponent.add(edge.getSource()); + vertexComponent.add(edge.getTarget()); + + edge = this.stack.removeLast(); + } + edgeComponent.add(edge); + // edgeComponent is an equivalence class. + + vertexComponent.add(edge.getSource()); + vertexComponent.add(edge.getTarget()); + + VertexComponentForbiddenFunction mask = + new VertexComponentForbiddenFunction( + vertexComponent); + UndirectedGraph biconnectedSubgraph = + new UndirectedMaskSubgraph( + this.graph, + mask); + for (Iterator iter = vertexComponent.iterator(); iter.hasNext();) { + V vertex = iter.next(); + this.vertex2block.put(vertex, biconnectedSubgraph); + getBiconnectedSubgraphs(vertex).add(biconnectedSubgraph); + } + addVertex(biconnectedSubgraph); + } + + private int dfsVisit(V s, V father) + { + this.numOrder++; + int minS = this.numOrder; + setNumOrder(s, this.numOrder); + + for ( + Iterator iter = this.graph.edgesOf(s).iterator(); + iter.hasNext();) + { + E edge = iter.next(); + V n = Graphs.getOppositeVertex(this.graph, edge, s); + if (getNumOrder(n) == 0) { + this.dfsTree.addVertex(n); + BCGEdge dfsEdge = new BCGEdge(s, n); + this.dfsTree.addEdge(s, n, dfsEdge); + + this.stack.add(dfsEdge); + + // minimum of the traverse orders of the "attach points" of + // the vertex n. + int minN = dfsVisit(n, s); + minS = Math.min(minN, minS); + if (minN >= getNumOrder(s)) { + // s is a cutpoint. + // it has a son whose "attach depth" is greater or equal. + biconnectedComponentFinished(s, n); + } + } else if ((getNumOrder(n) < getNumOrder(s)) && !n.equals(father)) { + BCGEdge backwardEdge = new BCGEdge(s, n); + this.stack.add(backwardEdge); + + // n is an "attach point" of s. {s->n} is a backward edge. + minS = Math.min(getNumOrder(n), minS); + } + } + + // minimum of the traverse orders of the "attach points" of + // the vertex s. + return minS; + } + + /** + * Returns the biconnected components containing the vertex. A vertex which + * is not a cutpoint is contained in exactly one component. A cutpoint is + * contained is at least 2 components. + * + * @param vertex vertex in the initial graph. + */ + private Set> getBiconnectedSubgraphs(V vertex) + { + Set> biconnectedSubgraphs = + this.vertex2biconnectedSubgraphs.get(vertex); + if (biconnectedSubgraphs == null) { + biconnectedSubgraphs = new HashSet>(); + this.vertex2biconnectedSubgraphs.put(vertex, biconnectedSubgraphs); + } + return biconnectedSubgraphs; + } + + /** + * Returns the traverse order of the vertex in the DFS. + */ + private int getNumOrder(V vertex) + { + assert (vertex != null); + + Integer numOrder = this.vertex2numOrder.get(vertex); + if (numOrder == null) { + return 0; + } else { + return numOrder.intValue(); + } + } + + private void setNumOrder(V vertex, int numOrder) + { + this.vertex2numOrder.put(vertex, Integer.valueOf(numOrder)); + } + + //~ Inner Classes ---------------------------------------------------------- + + private class BCGEdge + extends DefaultEdge + { + /** + */ + private static final long serialVersionUID = -5115006161815760059L; + + private V source; + + private V target; + + public BCGEdge(V source, V target) + { + super(); + this.source = source; + this.target = target; + } + + public V getSource() + { + return this.source; + } + + public V getTarget() + { + return this.target; + } + } + + private class VertexComponentForbiddenFunction + implements MaskFunctor + { + private Set vertexComponent; + + public VertexComponentForbiddenFunction(Set vertexComponent) + { + this.vertexComponent = vertexComponent; + } + + public boolean isEdgeMasked(E edge) + { + return false; + } + + public boolean isVertexMasked(V vertex) + { + if (this.vertexComponent.contains(vertex)) { + // vertex belongs to component then we do not mask it. + return false; + } else { + return true; + } + } + } +} + +// End BlockCutpointGraph.java diff --git a/wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java b/wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java new file mode 100644 index 0000000..bcce728 --- /dev/null +++ b/wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java @@ -0,0 +1,198 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * BronKerboschCliqueFinder.java + * ------------------- + * (C) Copyright 2005-2008, by Ewgenij Proschak and Contributors. + * + * Original Author: Ewgenij Proschak + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 21-Jul-2005 : Initial revision (EP); + * 26-Jul-2005 : Cleaned up and checked in (JVS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * This class implements Bron-Kerbosch clique detection algorithm as it is + * described in [Samudrala R.,Moult J.:A Graph-theoretic Algorithm for + * comparative Modeling of Protein Structure; J.Mol. Biol. (1998); vol 279; pp. + * 287-302] + * + * @author Ewgenij Proschak + */ +public class BronKerboschCliqueFinder +{ + //~ Instance fields -------------------------------------------------------- + + private final Graph graph; + + private Collection> cliques; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new clique finder. + * + * @param graph the graph in which cliques are to be found; graph must be + * simple + */ + public BronKerboschCliqueFinder(Graph graph) + { + this.graph = graph; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Finds all maximal cliques of the graph. A clique is maximal if it is + * impossible to enlarge it by adding another vertex from the graph. Note + * that a maximal clique is not necessarily the biggest clique in the graph. + * + * @return Collection of cliques (each of which is represented as a Set of + * vertices) + */ + public Collection> getAllMaximalCliques() + { + // TODO jvs 26-July-2005: assert that graph is simple + + cliques = new ArrayList>(); + List potential_clique = new ArrayList(); + List candidates = new ArrayList(); + List already_found = new ArrayList(); + candidates.addAll(graph.vertexSet()); + findCliques(potential_clique, candidates, already_found); + return cliques; + } + + /** + * Finds the biggest maximal cliques of the graph. + * + * @return Collection of cliques (each of which is represented as a Set of + * vertices) + */ + public Collection> getBiggestMaximalCliques() + { + // first, find all cliques + getAllMaximalCliques(); + + int maximum = 0; + Collection> biggest_cliques = new ArrayList>(); + for (Set clique : cliques) { + if (maximum < clique.size()) { + maximum = clique.size(); + } + } + for (Set clique : cliques) { + if (maximum == clique.size()) { + biggest_cliques.add(clique); + } + } + return biggest_cliques; + } + + private void findCliques( + List potential_clique, + List candidates, + List already_found) + { + List candidates_array = new ArrayList(candidates); + if (!end(candidates, already_found)) { + // for each candidate_node in candidates do + for (V candidate : candidates_array) { + List new_candidates = new ArrayList(); + List new_already_found = new ArrayList(); + + // move candidate node to potential_clique + potential_clique.add(candidate); + candidates.remove(candidate); + + // create new_candidates by removing nodes in candidates not + // connected to candidate node + for (V new_candidate : candidates) { + if (graph.containsEdge(candidate, new_candidate)) { + new_candidates.add(new_candidate); + } // of if + } // of for + + // create new_already_found by removing nodes in already_found + // not connected to candidate node + for (V new_found : already_found) { + if (graph.containsEdge(candidate, new_found)) { + new_already_found.add(new_found); + } // of if + } // of for + + // if new_candidates and new_already_found are empty + if (new_candidates.isEmpty() && new_already_found.isEmpty()) { + // potential_clique is maximal_clique + cliques.add(new HashSet(potential_clique)); + } // of if + else { + // recursive call + findCliques( + potential_clique, + new_candidates, + new_already_found); + } // of else + + // move candidate_node from potential_clique to already_found; + already_found.add(candidate); + potential_clique.remove(candidate); + } // of for + } // of if + } + + private boolean end(List candidates, List already_found) + { + // if a node in already_found is connected to all nodes in candidates + boolean end = false; + int edgecounter; + for (V found : already_found) { + edgecounter = 0; + for (V candidate : candidates) { + if (graph.containsEdge(found, candidate)) { + edgecounter++; + } // of if + } // of for + if (edgecounter == candidates.size()) { + end = true; + } + } // of for + return end; + } +} + +// End BronKerboschCliqueFinder.java diff --git a/wdl/org/jgrapht/alg/ChromaticNumber.java b/wdl/org/jgrapht/alg/ChromaticNumber.java new file mode 100644 index 0000000..84a7329 --- /dev/null +++ b/wdl/org/jgrapht/alg/ChromaticNumber.java @@ -0,0 +1,147 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * ChromaticNumber.java + * ------------------- + * (C) Copyright 2008-2008, by Andrew Newell and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): gpaschos@netscape.net, harshalv@telenav.com + * + * $Id$ + * + * Changes + * ------- + * 24-Dec-2008 : Initial revision (AN); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.util.*; +import org.jgrapht.graph.*; + + +/** + * Allows the + * chromatic number of a graph to be calculated. This is the minimal number + * of colors needed to color each vertex such that no two adjacent vertices + * share the same color. This algorithm will not find the true chromatic number, + * since this is an NP-complete problem. So, a greedy algorithm will find an + * approximate chromatic number. + * + * @author Andrew Newell + * @since Dec 21, 2008 + */ +public abstract class ChromaticNumber +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Finds the number of colors required for a greedy coloring of the graph. + * + * @param g an undirected graph to find the chromatic number of + * + * @return integer the approximate chromatic number from the greedy + * algorithm + */ + public static int findGreedyChromaticNumber(UndirectedGraph g) + { + Map> coloredGroups = findGreedyColoredGroups(g); + return coloredGroups.keySet().size(); + } + + /** + * Finds a greedy coloring of the graph. + * + * @param g an undirected graph for which to find the coloring + */ + public static Map> findGreedyColoredGroups( + UndirectedGraph g) + { + // A copy of the graph is made, so that elements of the graph may be + // removed to carry out the algorithm + UndirectedGraph sg = new UndirectedSubgraph(g, null, null); + + // The Vertices will be sorted in decreasing order by degree, so that + // higher degree vertices have priority to be colored first + VertexDegreeComparator comp = + new VertexDegreeComparator(sg); + List sortedVertices = new LinkedList(sg.vertexSet()); + Collections.sort(sortedVertices, comp); + Collections.reverse(sortedVertices); + + int color; + + // create a map which will hold color as key and Set as value + Map> coloredGroups = new HashMap>(); + + // We'll attempt to color each vertex with a single color each + // iteration, and these vertices will be removed from the graph at the + // end of each iteration + for (color = 0; sg.vertexSet().size() > 0; color++) { + // This set will contain vertices that are colored with the + // current color of this iteration + Set currentColor = new HashSet(); + for ( + Iterator iter = sortedVertices.iterator(); + iter.hasNext();) + { + V v = iter.next(); + + // Add new vertices to be colored as long as they are not + // adjacent with any other vertex that has already been colored + // with the current color + boolean flag = true; + for ( + Iterator innerIter = currentColor.iterator(); + innerIter.hasNext();) + { + V temp = innerIter.next(); + if (sg.containsEdge(temp, v)) { + flag = false; + break; + } + } + if (flag) { + currentColor.add(v); + iter.remove(); + } + } + + // Add all these vertices as a group for this color + coloredGroups.put(color, currentColor); + + // Remove vertices from the graph and then repeat the process for + // the next iteration + sg.removeAllVertices(currentColor); + } + return coloredGroups; + } +} + +// End ChromaticNumber.java diff --git a/wdl/org/jgrapht/alg/ConnectivityInspector.java b/wdl/org/jgrapht/alg/ConnectivityInspector.java new file mode 100644 index 0000000..d242878 --- /dev/null +++ b/wdl/org/jgrapht/alg/ConnectivityInspector.java @@ -0,0 +1,302 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * ConnectivityInspector.java + * -------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): John V. Sichi + * Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 06-Aug-2003 : Initial revision (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 07-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; +import org.jgrapht.graph.*; +import org.jgrapht.traverse.*; + + +/** + * Allows obtaining various connectivity aspects of a graph. The inspected + * graph is specified at construction time and cannot be modified. + * Currently, the inspector supports connected components for an undirected + * graph and weakly connected components for a directed graph. To find strongly + * connected components, use {@link StrongConnectivityInspector} instead. + * + *

The inspector methods work in a lazy fashion: no computation is performed + * unless immediately necessary. Computation are done once and results and + * cached within this class for future need.

+ * + *

The inspector is also a {@link org.jgrapht.event.GraphListener}. If added + * as a listener to the inspected graph, the inspector will amend internal + * cached results instead of recomputing them. It is efficient when a few + * modifications are applied to a large graph. If many modifications are + * expected it will not be efficient due to added overhead on graph update + * operations. If inspector is added as listener to a graph other than the one + * it inspects, results are undefined.

+ * + * @author Barak Naveh + * @author John V. Sichi + * @since Aug 6, 2003 + */ +public class ConnectivityInspector + implements GraphListener +{ + //~ Instance fields -------------------------------------------------------- + + List> connectedSets; + Map> vertexToConnectedSet; + private Graph graph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a connectivity inspector for the specified undirected graph. + * + * @param g the graph for which a connectivity inspector to be created. + */ + public ConnectivityInspector(UndirectedGraph g) + { + init(); + this.graph = g; + } + + /** + * Creates a connectivity inspector for the specified directed graph. + * + * @param g the graph for which a connectivity inspector to be created. + */ + public ConnectivityInspector(DirectedGraph g) + { + init(); + this.graph = new AsUndirectedGraph(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Test if the inspected graph is connected. An empty graph is not + * considered connected. + * + * @return true if and only if inspected graph is connected. + */ + public boolean isGraphConnected() + { + return lazyFindConnectedSets().size() == 1; + } + + /** + * Returns a set of all vertices that are in the maximally connected + * component together with the specified vertex. For more on maximally + * connected component, see + * http://www.nist.gov/dads/HTML/maximallyConnectedComponent.html. + * + * @param vertex the vertex for which the connected set to be returned. + * + * @return a set of all vertices that are in the maximally connected + * component together with the specified vertex. + */ + public Set connectedSetOf(V vertex) + { + Set connectedSet = vertexToConnectedSet.get(vertex); + + if (connectedSet == null) { + connectedSet = new HashSet(); + + BreadthFirstIterator i = + new BreadthFirstIterator(graph, vertex); + + while (i.hasNext()) { + connectedSet.add(i.next()); + } + + vertexToConnectedSet.put(vertex, connectedSet); + } + + return connectedSet; + } + + /** + * Returns a list of Set s, where each set contains all + * vertices that are in the same maximally connected component. All graph + * vertices occur in exactly one set. For more on maximally connected + * component, see + * http://www.nist.gov/dads/HTML/maximallyConnectedComponent.html. + * + * @return Returns a list of Set s, where each set contains all + * vertices that are in the same maximally connected component. + */ + public List> connectedSets() + { + return lazyFindConnectedSets(); + } + + /** + * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) + */ + public void edgeAdded(GraphEdgeChangeEvent e) + { + init(); // for now invalidate cached results, in the future need to + // amend them. + } + + /** + * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) + */ + public void edgeRemoved(GraphEdgeChangeEvent e) + { + init(); // for now invalidate cached results, in the future need to + // amend them. + } + + /** + * Tests if there is a path from the specified source vertex to the + * specified target vertices. For a directed graph, direction is ignored for + * this interpretation of path. + * + *

Note: Future versions of this method might not ignore edge directions + * for directed graphs.

+ * + * @param sourceVertex one end of the path. + * @param targetVertex another end of the path. + * + * @return true if and only if there is a path from the source + * vertex to the target vertex. + */ + public boolean pathExists(V sourceVertex, V targetVertex) + { + /* + * TODO: Ignoring edge direction for directed graph may be + * confusing. For directed graphs, consider Dijkstra's algorithm. + */ + Set sourceSet = connectedSetOf(sourceVertex); + + return sourceSet.contains(targetVertex); + } + + /** + * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) + */ + public void vertexAdded(GraphVertexChangeEvent e) + { + init(); // for now invalidate cached results, in the future need to + // amend them. + } + + /** + * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) + */ + public void vertexRemoved(GraphVertexChangeEvent e) + { + init(); // for now invalidate cached results, in the future need to + // amend them. + } + + private void init() + { + connectedSets = null; + vertexToConnectedSet = new HashMap>(); + } + + private List> lazyFindConnectedSets() + { + if (connectedSets == null) { + connectedSets = new ArrayList>(); + + Set vertexSet = graph.vertexSet(); + + if (vertexSet.size() > 0) { + BreadthFirstIterator i = + new BreadthFirstIterator(graph, null); + i.addTraversalListener(new MyTraversalListener()); + + while (i.hasNext()) { + i.next(); + } + } + } + + return connectedSets; + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * A traversal listener that groups all vertices according to to their + * containing connected set. + * + * @author Barak Naveh + * @since Aug 6, 2003 + */ + private class MyTraversalListener + extends TraversalListenerAdapter + { + private Set currentConnectedSet; + + /** + * @see TraversalListenerAdapter#connectedComponentFinished(ConnectedComponentTraversalEvent) + */ + public void connectedComponentFinished( + ConnectedComponentTraversalEvent e) + { + connectedSets.add(currentConnectedSet); + } + + /** + * @see TraversalListenerAdapter#connectedComponentStarted(ConnectedComponentTraversalEvent) + */ + public void connectedComponentStarted( + ConnectedComponentTraversalEvent e) + { + currentConnectedSet = new HashSet(); + } + + /** + * @see TraversalListenerAdapter#vertexTraversed(VertexTraversalEvent) + */ + public void vertexTraversed(VertexTraversalEvent e) + { + V v = e.getVertex(); + currentConnectedSet.add(v); + vertexToConnectedSet.put(v, currentConnectedSet); + } + } +} + +// End ConnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/CycleDetector.java b/wdl/org/jgrapht/alg/CycleDetector.java new file mode 100644 index 0000000..3cd1a60 --- /dev/null +++ b/wdl/org/jgrapht/alg/CycleDetector.java @@ -0,0 +1,271 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * CycleDetector.java + * ------------------ + * (C) Copyright 2004-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 16-Sept-2004 : Initial revision (JVS); + * 07-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.traverse.*; + + +/** + * Performs cycle detection on a graph. The inspected graph is specified + * at construction time and cannot be modified. Currently, the detector supports + * only directed graphs. + * + * @author John V. Sichi + * @since Sept 16, 2004 + */ +public class CycleDetector +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Graph on which cycle detection is being performed. + */ + DirectedGraph graph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a cycle detector for the specified graph. Currently only directed + * graphs are supported. + * + * @param graph the DirectedGraph in which to detect cycles + */ + public CycleDetector(DirectedGraph graph) + { + this.graph = graph; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Performs yes/no cycle detection on the entire graph. + * + * @return true iff the graph contains at least one cycle + */ + public boolean detectCycles() + { + try { + execute(null, null); + } catch (CycleDetectedException ex) { + return true; + } + + return false; + } + + /** + * Performs yes/no cycle detection on an individual vertex. + * + * @param v the vertex to test + * + * @return true if v is on at least one cycle + */ + public boolean detectCyclesContainingVertex(V v) + { + try { + execute(null, v); + } catch (CycleDetectedException ex) { + return true; + } + + return false; + } + + /** + * Finds the vertex set for the subgraph of all cycles. + * + * @return set of all vertices which participate in at least one cycle in + * this graph + */ + public Set findCycles() + { + // ProbeIterator can't be used to handle this case, + // so use StrongConnectivityInspector instead. + StrongConnectivityInspector inspector = + new StrongConnectivityInspector(graph); + List> components = inspector.stronglyConnectedSets(); + + // A vertex participates in a cycle if either of the following is + // true: (a) it is in a component whose size is greater than 1 + // or (b) it is a self-loop + + Set set = new HashSet(); + for (Set component : components) { + if (component.size() > 1) { + // cycle + set.addAll(component); + } else { + V v = component.iterator().next(); + if (graph.containsEdge(v, v)) { + // self-loop + set.add(v); + } + } + } + + return set; + } + + /** + * Finds the vertex set for the subgraph of all cycles which contain a + * particular vertex. + * + *

REVIEW jvs 25-Aug-2006: This implementation is not guaranteed to cover + * all cases. If you want to be absolutely certain that you report vertices + * from all cycles containing v, it's safer (but less efficient) to use + * StrongConnectivityInspector instead and return the strongly connected + * component containing v. + * + * @param v the vertex to test + * + * @return set of all vertices reachable from v via at least one cycle + */ + public Set findCyclesContainingVertex(V v) + { + Set set = new HashSet(); + execute(set, v); + + return set; + } + + private void execute(Set s, V v) + { + ProbeIterator iter = new ProbeIterator(s, v); + + while (iter.hasNext()) { + iter.next(); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Exception thrown internally when a cycle is detected during a yes/no + * cycle test. Must be caught by top-level detection method. + */ + private static class CycleDetectedException + extends RuntimeException + { + private static final long serialVersionUID = 3834305137802950712L; + } + + /** + * Version of DFS which maintains a backtracking path used to probe for + * cycles. + */ + private class ProbeIterator + extends DepthFirstIterator + { + private List path; + private Set cycleSet; + private V root; + + ProbeIterator(Set cycleSet, V startVertex) + { + super(graph, startVertex); + root = startVertex; + this.cycleSet = cycleSet; + path = new ArrayList(); + } + + /** + * {@inheritDoc} + */ + protected void encounterVertexAgain(V vertex, E edge) + { + super.encounterVertexAgain(vertex, edge); + + int i; + + if (root != null) { + // For rooted detection, the path must either + // double back to the root, or to a node of a cycle + // which has already been detected. + if (vertex.equals(root)) { + i = 0; + } else if ((cycleSet != null) && cycleSet.contains(vertex)) { + i = 0; + } else { + return; + } + } else { + i = path.indexOf(vertex); + } + + if (i > -1) { + if (cycleSet == null) { + // we're doing yes/no cycle detection + throw new CycleDetectedException(); + } else { + for (; i < path.size(); ++i) { + cycleSet.add(path.get(i)); + } + } + } + } + + /** + * {@inheritDoc} + */ + protected V provideNextVertex() + { + V v = super.provideNextVertex(); + + // backtrack + for (int i = path.size() - 1; i >= 0; --i) { + if (graph.containsEdge(path.get(i), v)) { + break; + } + + path.remove(i); + } + + path.add(v); + + return v; + } + } +} + +// End CycleDetector.java diff --git a/wdl/org/jgrapht/alg/DijkstraShortestPath.java b/wdl/org/jgrapht/alg/DijkstraShortestPath.java new file mode 100644 index 0000000..43a6532 --- /dev/null +++ b/wdl/org/jgrapht/alg/DijkstraShortestPath.java @@ -0,0 +1,218 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * DijkstraShortestPath.java + * ------------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 02-Sep-2003 : Initial revision (JVS); + * 29-May-2005 : Make non-static and add radius support (JVS); + * 07-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; +import org.jgrapht.traverse.*; + + +/** + * An implementation of Dijkstra's + * shortest path algorithm using ClosestFirstIterator. + * + * @author John V. Sichi + * @since Sep 2, 2003 + */ +public final class DijkstraShortestPath +{ + //~ Instance fields -------------------------------------------------------- + + private GraphPath path; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates and executes a new DijkstraShortestPath algorithm instance. An + * instance is only good for a single search; after construction, it can be + * accessed to retrieve information about the path found. + * + * @param graph the graph to be searched + * @param startVertex the vertex at which the path should start + * @param endVertex the vertex at which the path should end + */ + public DijkstraShortestPath(Graph graph, + V startVertex, + V endVertex) + { + this(graph, startVertex, endVertex, Double.POSITIVE_INFINITY); + } + + /** + * Creates and executes a new DijkstraShortestPath algorithm instance. An + * instance is only good for a single search; after construction, it can be + * accessed to retrieve information about the path found. + * + * @param graph the graph to be searched + * @param startVertex the vertex at which the path should start + * @param endVertex the vertex at which the path should end + * @param radius limit on path length, or Double.POSITIVE_INFINITY for + * unbounded search + */ + public DijkstraShortestPath( + Graph graph, + V startVertex, + V endVertex, + double radius) + { + if (!graph.containsVertex(endVertex)) { + throw new IllegalArgumentException( + "graph must contain the end vertex"); + } + + ClosestFirstIterator iter = + new ClosestFirstIterator(graph, startVertex, radius); + + while (iter.hasNext()) { + V vertex = iter.next(); + + if (vertex.equals(endVertex)) { + createEdgeList(graph, iter, startVertex, endVertex); + return; + } + } + + path = null; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Return the edges making up the path found. + * + * @return List of Edges, or null if no path exists + */ + public List getPathEdgeList() + { + if (path == null) { + return null; + } else { + return path.getEdgeList(); + } + } + + /** + * Return the path found. + * + * @return path representation, or null if no path exists + */ + public GraphPath getPath() + { + return path; + } + + /** + * Return the length of the path found. + * + * @return path length, or Double.POSITIVE_INFINITY if no path exists + */ + public double getPathLength() + { + if (path == null) { + return Double.POSITIVE_INFINITY; + } else { + return path.getWeight(); + } + } + + /** + * Convenience method to find the shortest path via a single static method + * call. If you need a more advanced search (e.g. limited by radius, or + * computation of the path length), use the constructor instead. + * + * @param graph the graph to be searched + * @param startVertex the vertex at which the path should start + * @param endVertex the vertex at which the path should end + * + * @return List of Edges, or null if no path exists + */ + public static List findPathBetween( + Graph graph, + V startVertex, + V endVertex) + { + DijkstraShortestPath alg = + new DijkstraShortestPath( + graph, + startVertex, + endVertex); + + return alg.getPathEdgeList(); + } + + private void createEdgeList( + Graph graph, + ClosestFirstIterator iter, + V startVertex, + V endVertex) + { + List edgeList = new ArrayList(); + + V v = endVertex; + + while (true) { + E edge = iter.getSpanningTreeEdge(v); + + if (edge == null) { + break; + } + + edgeList.add(edge); + v = Graphs.getOppositeVertex(graph, edge, v); + } + + Collections.reverse(edgeList); + double pathLength = iter.getShortestPathLength(endVertex); + path = + new GraphPathImpl( + graph, + startVertex, + endVertex, + edgeList, + pathLength); + } +} + +// End DijkstraShortestPath.java diff --git a/wdl/org/jgrapht/alg/DirectedNeighborIndex.java b/wdl/org/jgrapht/alg/DirectedNeighborIndex.java new file mode 100644 index 0000000..fdf7557 --- /dev/null +++ b/wdl/org/jgrapht/alg/DirectedNeighborIndex.java @@ -0,0 +1,233 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * DirectedNeighborIndex.java + * -------------------------- + * (C) Copyright 2005-2008, by Charles Fry and Contributors. + * + * Original Author: Charles Fry + * + * $Id$ + * + * Changes + * ------- + * 13-Dec-2005 : Initial revision (CF); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.NeighborIndex.*; +import org.jgrapht.event.*; + + +/** + * Maintains a cache of each vertex's neighbors. While lists of neighbors can be + * obtained from {@link Graphs}, they are re-calculated at each invocation by + * walking a vertex's incident edges, which becomes inordinately expensive when + * performed often. + * + *

A vertex's neighbors are cached the first time they are asked for (i.e. + * the index is built on demand). The index will only be updated automatically + * if it is added to the associated graph as a listener. If it is added as a + * listener to a graph other than the one it indexes, results are undefined.

+ * + * @author Charles Fry + * @since Dec 13, 2005 + */ +public class DirectedNeighborIndex + implements GraphListener +{ + //~ Instance fields -------------------------------------------------------- + + Map> predecessorMap = new HashMap>(); + Map> successorMap = new HashMap>(); + private DirectedGraph graph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a neighbor index for the specified directed graph. + * + * @param g the graph for which a neighbor index is to be created. + */ + public DirectedNeighborIndex(DirectedGraph g) + { + graph = g; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the set of vertices which are the predecessors of a specified + * vertex. The returned set is backed by the index, and will be updated when + * the graph changes as long as the index has been added as a listener to + * the graph. + * + * @param v the vertex whose predecessors are desired + * + * @return all unique predecessors of the specified vertex + */ + public Set predecessorsOf(V v) + { + return getPredecessors(v).getNeighbors(); + } + + /** + * Returns the set of vertices which are the predecessors of a specified + * vertex. If the graph is a multigraph, vertices may appear more than once + * in the returned list. Because a list of predecessors can not be + * efficiently maintained, it is reconstructed on every invocation by + * duplicating entries in the neighbor set. It is thus more efficient to use + * {@link #predecessorsOf(Object)} unless duplicate neighbors are required. + * + * @param v the vertex whose predecessors are desired + * + * @return all predecessors of the specified vertex + */ + public List predecessorListOf(V v) + { + return getPredecessors(v).getNeighborList(); + } + + /** + * Returns the set of vertices which are the successors of a specified + * vertex. The returned set is backed by the index, and will be updated when + * the graph changes as long as the index has been added as a listener to + * the graph. + * + * @param v the vertex whose successors are desired + * + * @return all unique successors of the specified vertex + */ + public Set successorsOf(V v) + { + return getSuccessors(v).getNeighbors(); + } + + /** + * Returns the set of vertices which are the successors of a specified + * vertex. If the graph is a multigraph, vertices may appear more than once + * in the returned list. Because a list of successors can not be efficiently + * maintained, it is reconstructed on every invocation by duplicating + * entries in the neighbor set. It is thus more efficient to use {@link + * #successorsOf(Object)} unless duplicate neighbors are required. + * + * @param v the vertex whose successors are desired + * + * @return all successors of the specified vertex + */ + public List successorListOf(V v) + { + return getSuccessors(v).getNeighborList(); + } + + /** + * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) + */ + public void edgeAdded(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + V source = graph.getEdgeSource(edge); + V target = graph.getEdgeTarget(edge); + + // if a map does not already contain an entry, + // then skip addNeighbor, since instantiating the map + // will take care of processing the edge (which has already + // been added) + + if (successorMap.containsKey(source)) { + getSuccessors(source).addNeighbor(target); + } else { + getSuccessors(source); + } + if (predecessorMap.containsKey(target)) { + getPredecessors(target).addNeighbor(source); + } else { + getPredecessors(target); + } + } + + /** + * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) + */ + public void edgeRemoved(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + V source = e.getEdgeSource(); + V target = e.getEdgeTarget(); + if (successorMap.containsKey(source)) { + successorMap.get(source).removeNeighbor(target); + } + if (predecessorMap.containsKey(target)) { + predecessorMap.get(target).removeNeighbor(source); + } + } + + /** + * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) + */ + public void vertexAdded(GraphVertexChangeEvent e) + { + // nothing to cache until there are edges + } + + /** + * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) + */ + public void vertexRemoved(GraphVertexChangeEvent e) + { + predecessorMap.remove(e.getVertex()); + successorMap.remove(e.getVertex()); + } + + private Neighbors getPredecessors(V v) + { + Neighbors neighbors = predecessorMap.get(v); + if (neighbors == null) { + neighbors = + new Neighbors(v, + Graphs.predecessorListOf(graph, v)); + predecessorMap.put(v, neighbors); + } + return neighbors; + } + + private Neighbors getSuccessors(V v) + { + Neighbors neighbors = successorMap.get(v); + if (neighbors == null) { + neighbors = + new Neighbors(v, + Graphs.successorListOf(graph, v)); + successorMap.put(v, neighbors); + } + return neighbors; + } +} + +// End DirectedNeighborIndex.java diff --git a/wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java b/wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java new file mode 100644 index 0000000..866b4d3 --- /dev/null +++ b/wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java @@ -0,0 +1,194 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2012, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * EdmondsBlossomShrinking.java + * ------------------------- + * (C) Copyright 2012-2012, by Alejandro Ramon Lopez del Huerto and Contributors. + * + * Original Author: Alejandro Ramon Lopez del Huerto + * Contributor(s): + * + * Changes + * ------- + * 24-Jan-2012 : Initial revision (ARLH); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + +/** + * An implementation of Edmonds Blossom Shrinking algorithm for constructing + * maximum matchings on graphs. The algorithm runs in time O(V^4). + * + * @author Alejandro R. Lopez del Huerto + * @since Jan 24, 2012 + */ +public class EdmondsBlossomShrinking +{ + // ~ Instance fields + // -------------------------------------------------------- + + private Map match; + private Map p; + private Map base; + private Queue q; + private Set used; + private Set blossom; + + // ~ Methods + // ---------------------------------------------------------------- + + /** + * Runs the algorithm on the input graph and returns the match edge set. + * + * @param g + * The graph to be matched + * @return set of Edges + */ + public Set findMatch(final UndirectedGraph g) + { + Set result = new ArrayUnenforcedSet(); + match = new HashMap(); + p = new HashMap(); + q = new ArrayDeque(); + base = new HashMap(); + used = new HashSet(); + blossom = new HashSet(); + + for (V i : g.vertexSet()) { + if (!match.containsKey(i)) { + V v = findPath(g, i); + while (v != null) { + V pv = p.get(v); + V ppv = match.get(pv); + match.put(v, pv); + match.put(pv, v); + v = ppv; + } + } + } + + Set seen = new HashSet(); + for (V v : g.vertexSet()) { + if (!seen.contains(v) && match.containsKey(v)) { + seen.add(v); + seen.add(match.get(v)); + result.add(g.getEdge(v, match.get(v))); + } + } + + return result; + } + + private V findPath(UndirectedGraph g, V root) + { + used.clear(); + p.clear(); + base.clear(); + + for (V i : g.vertexSet()) { + base.put(i, i); + } + + used.add(root); + q.add(root); + while (!q.isEmpty()) { + V v = q.remove(); + for (V to : g.vertexSet()) { + if (!g.containsEdge(v, to)) { + continue; + } + + if ((base.get(v) == base.get(to)) || (match.get(v) == to)) { + continue; + } + if (to == root || (match.containsKey(to)) + && (p.containsKey(match.get(to)))) { + V curbase = lca(g, v, to); + blossom.clear(); + markPath(g, v, curbase, to); + markPath(g, to, curbase, v); + + for (V i : g.vertexSet()) { + if (base.containsKey(i) + && blossom.contains(base.get(i))) + { + base.put(i, curbase); + if (!used.contains(i)) { + used.add(i); + q.add(i); + } + } + } + } else if (!p.containsKey(to)) { + p.put(to, v); + if (!match.containsKey(to)) { + return to; + } + to = match.get(to); + used.add(to); + q.add(to); + } + } + } + return null; + } + + private void markPath(UndirectedGraph g, V v, V b, V children) + { + while (base.get(v) != b) { + blossom.add(base.get(v)); + blossom.add(base.get(match.get(v))); + p.put(v, children); + children = match.get(v); + v = p.get(match.get(v)); + } + } + + private V lca(UndirectedGraph g, V a, V b) + { + Set seen = new HashSet(); + for (;;) { + a = base.get(a); + seen.add(a); + if (!match.containsKey(a)) { + break; + } + a = p.get(match.get(a)); + } + for (;;) { + b = base.get(b); + if (seen.contains(b)) { + return b; + } + b = p.get(match.get(b)); + } + } + +} diff --git a/wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java b/wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java new file mode 100644 index 0000000..85d80d1 --- /dev/null +++ b/wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java @@ -0,0 +1,361 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EdmondsKarpMaximumFlow.java + * ----------------- + * (C) Copyright 2008-2008, by Ilya Razenshteyn and Contributors. + * + * Original Author: Ilya Razenshteyn + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * A flow network is a + * directed graph where each edge has a capacity and each edge receives a flow. + * The amount of flow on an edge can not exceed the capacity of the edge (note, + * that all capacities must be non-negative). A flow must satisfy the + * restriction that the amount of flow into a vertex equals the amount of flow + * out of it, except when it is a source, which "produces" flow, or sink, which + * "consumes" flow. + * + *

This class computes maximum flow in a network using Edmonds-Karp + * algorithm. Be careful: for large networks this algorithm may consume + * significant amount of time (its upper-bound complexity is O(VE^2), where V - + * amount of vertices, E - amount of edges in the network). + * + *

For more details see Andrew V. Goldberg's Combinatorial Optimization + * (Lecture Notes). + */ +public final class EdmondsKarpMaximumFlow +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Default tolerance. + */ + public static final double DEFAULT_EPSILON = 0.000000001; + + //~ Instance fields -------------------------------------------------------- + + private DirectedGraph network; // our network + private double epsilon; // tolerance (DEFAULT_EPSILON or user-defined) + private int currentSource; // current source vertex + private int currentSink; // current sink vertex + private Map maximumFlow; // current maximum flow + private Double maximumFlowValue; // current maximum flow value + private int numNodes; // number of nodes in the network + private Map indexer; // mapping from vertices to their indexes + // in the internal representation + private List nodes; // internal representation of the network + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructs MaximumFlow instance to work with a copy of + * network. Current source and sink are set to null. If + * network is weighted, then capacities are weights, otherwise all + * capacities are equal to one. Doubles are compared using + * DEFAULT_EPSILON tolerance. + * + * @param network network, where maximum flow will be calculated + */ + public EdmondsKarpMaximumFlow(DirectedGraph network) + { + this(network, DEFAULT_EPSILON); + } + + /** + * Constructs MaximumFlow instance to work with a copy of + * network. Current source and sink are set to null. If + * network is weighted, then capacities are weights, otherwise all + * capacities are equal to one. + * + * @param network network, where maximum flow will be calculated + * @param epsilon tolerance for comparing doubles + */ + public EdmondsKarpMaximumFlow(DirectedGraph network, + double epsilon) + { + if (network == null) { + throw new NullPointerException("network is null"); + } + if (epsilon <= 0) { + throw new IllegalArgumentException( + "invalid epsilon (must be positive)"); + } + for (E e : network.edgeSet()) { + if (network.getEdgeWeight(e) < -epsilon) { + throw new IllegalArgumentException( + "invalid capacity (must be non-negative)"); + } + } + + this.network = network; + this.epsilon = epsilon; + + currentSource = -1; + currentSink = -1; + maximumFlow = null; + maximumFlowValue = null; + + buildInternalNetwork(); + } + + //~ Methods ---------------------------------------------------------------- + + // converting the original network into internal more convenient format + private void buildInternalNetwork() + { + numNodes = network.vertexSet().size(); + nodes = new ArrayList(); + Iterator it = network.vertexSet().iterator(); + indexer = new HashMap(); + for (int i = 0; i < numNodes; i++) { + V currentNode = it.next(); + nodes.add(new Node(currentNode)); + indexer.put(currentNode, i); + } + for (int i = 0; i < numNodes; i++) { + V we = nodes.get(i).prototype; + for (E e : network.outgoingEdgesOf(we)) { + V he = network.getEdgeTarget(e); + int j = indexer.get(he); + Arc e1 = new Arc(i, j, network.getEdgeWeight(e), e); + Arc e2 = new Arc(j, i, 0.0, null); + e1.reversed = e2; + e2.reversed = e1; + nodes.get(i).outgoingArcs.add(e1); + nodes.get(j).outgoingArcs.add(e2); + } + } + } + + /** + * Sets current source to source, current sink to sink, + * then calculates maximum flow from source to sink. Note, + * that source and sink must be vertices of the + * network passed to the constructor, and they must be different. + * + * @param source source vertex + * @param sink sink vertex + */ + public void calculateMaximumFlow( + V source, + V sink) + { + if (!network.containsVertex(source)) { + throw new IllegalArgumentException( + "invalid source (null or not from this network)"); + } + if (!network.containsVertex(sink)) { + throw new IllegalArgumentException( + "invalid sink (null or not from this network)"); + } + + if (source.equals(sink)) { + throw new IllegalArgumentException("source is equal to sink"); + } + + currentSource = indexer.get(source); + currentSink = indexer.get(sink); + + for (int i = 0; i < numNodes; i++) { + for (Arc currentArc : nodes.get(i).outgoingArcs) { + currentArc.flow = 0.0; + } + } + maximumFlowValue = 0.0; + for (;;) { + breadthFirstSearch(); + if (!nodes.get(currentSink).visited) { + maximumFlow = new HashMap(); + for (int i = 0; i < numNodes; i++) { + for (Arc currentArc : nodes.get(i).outgoingArcs) { + if (currentArc.prototype != null) { + maximumFlow.put( + currentArc.prototype, + currentArc.flow); + } + } + } + return; + } + augmentFlow(); + } + } + + private void breadthFirstSearch() + { + for (int i = 0; i < numNodes; i++) { + nodes.get(i).visited = false; + } + Queue queue = new LinkedList(); + queue.offer(currentSource); + nodes.get(currentSource).visited = true; + nodes.get(currentSource).flowAmount = Double.POSITIVE_INFINITY; + while (queue.size() != 0) { + int currentNode = queue.poll(); + for (Arc currentArc : nodes.get(currentNode).outgoingArcs) { + if ((currentArc.flow + epsilon) < currentArc.capacity) { + if (!nodes.get(currentArc.head).visited) { + nodes.get(currentArc.head).visited = true; + nodes.get(currentArc.head).flowAmount = + Math.min( + nodes.get(currentNode).flowAmount, + currentArc.capacity - currentArc.flow); + nodes.get(currentArc.head).lastArc = currentArc; + queue.add(currentArc.head); + } + } + } + } + } + + private void augmentFlow() + { + double deltaFlow = nodes.get(currentSink).flowAmount; + maximumFlowValue += deltaFlow; + int currentNode = currentSink; + while (currentNode != currentSource) { + nodes.get(currentNode).lastArc.flow += deltaFlow; + nodes.get(currentNode).lastArc.reversed.flow -= deltaFlow; + currentNode = nodes.get(currentNode).lastArc.tail; + } + } + + /** + * Returns maximum flow value, that was calculated during last + * calculateMaximumFlow call, or null, if there was no + * calculateMaximumFlow calls. + * + * @return maximum flow value + */ + public Double getMaximumFlowValue() + { + return maximumFlowValue; + } + + /** + * Returns maximum flow, that was calculated during last + * calculateMaximumFlow call, or null, if there was no + * calculateMaximumFlow calls. + * + * @return read-only mapping from edges to doubles - flow values + */ + public Map getMaximumFlow() + { + if (maximumFlow == null) { + return null; + } + return Collections.unmodifiableMap(maximumFlow); + } + + /** + * Returns current source vertex, or null if there was no + * calculateMaximumFlow calls. + * + * @return current source + */ + public V getCurrentSource() + { + if (currentSource == -1) { + return null; + } + return nodes.get(currentSource).prototype; + } + + /** + * Returns current sink vertex, or null if there was no + * calculateMaximumFlow calls. + * + * @return current sink + */ + public V getCurrentSink() + { + if (currentSink == -1) { + return null; + } + return nodes.get(currentSink).prototype; + } + + //~ Inner Classes ---------------------------------------------------------- + + // class used for internal representation of network + class Node + { + V prototype; // corresponding node in the original network + List outgoingArcs = new ArrayList(); // list of outgoing arcs + // in the residual + // network + boolean visited; // this mark is used during BFS to mark visited nodes + Arc lastArc; // last arc in the shortest path + double flowAmount; // amount of flow, we are able to push here + + Node( + V prototype) + { + this.prototype = prototype; + } + } + + // class used for internal representation of network + class Arc + { + int tail; // "from" + int head; // "to" + double capacity; // capacity (can be zero) + double flow; // current flow (can be negative) + Arc reversed; // for each arc in the original network we are to create + // reversed arc + E prototype; // corresponding edge in the original network, can be null, + // if it is reversed arc + + Arc( + int tail, + int head, + double capacity, + E prototype) + { + this.tail = tail; + this.head = head; + this.capacity = capacity; + this.prototype = prototype; + } + } +} + +// End EdmondsKarpMaximumFlow.java diff --git a/wdl/org/jgrapht/alg/EulerianCircuit.java b/wdl/org/jgrapht/alg/EulerianCircuit.java new file mode 100644 index 0000000..0ea4e8b --- /dev/null +++ b/wdl/org/jgrapht/alg/EulerianCircuit.java @@ -0,0 +1,148 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * EulerianCircuit.java + * ------------------- + * (C) Copyright 2008-2008, by Andrew Newell and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 24-Dec-2008 : Initial revision (AN); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + * This algorithm will check whether a graph is Eulerian (hence it contains an + * Eulerian + * circuit). Also, if a graph is Eulerian, the caller can obtain a list of + * vertices making up the Eulerian circuit. An Eulerian circuit is a circuit + * which traverses each edge exactly once. + * + * @author Andrew Newell + * @since Dec 21, 2008 + */ +public abstract class EulerianCircuit +{ + //~ Methods ---------------------------------------------------------------- + + /** + * This method will check whether the graph passed in is Eulerian or not. + * + * @param g The graph to be checked + * + * @return true for Eulerian and false for non-Eulerian + */ + public static boolean isEulerian(UndirectedGraph g) + { + // If the graph is not connected, then no Eulerian circuit exists + if (!(new ConnectivityInspector(g)).isGraphConnected()) { + return false; + } + + // A graph is Eulerian if and only if all vertices have even degree + // So, this code will check for that + Iterator iter = g.vertexSet().iterator(); + while (iter.hasNext()) { + V v = iter.next(); + if ((g.degreeOf(v) % 2) == 1) { + return false; + } + } + return true; + } + + /** + * This method will return a list of vertices which represents the Eulerian + * circuit of the graph. + * + * @param g The graph to find an Eulerian circuit + * + * @return null if no Eulerian circuit exists, or a list of vertices + * representing the Eulerian circuit if one does exist + */ + public static List getEulerianCircuitVertices( + UndirectedGraph g) + { + // If the graph is not Eulerian then just return a null since no + // Eulerian circuit exists + if (!isEulerian(g)) { + return null; + } + + // The circuit will be represented by a linked list + List path = new LinkedList(); + UndirectedGraph sg = new UndirectedSubgraph(g, null, null); + path.add(sg.vertexSet().iterator().next()); + + // Algorithm for finding an Eulerian circuit Basically this will find an + // arbitrary circuit, then it will find another arbitrary circuit until + // every edge has been traversed + while (sg.edgeSet().size() > 0) { + V v = null; + + // Find a vertex which has an edge that hasn't been traversed yet, + // and keep its index position in the circuit list + int index = 0; + for (Iterator iter = path.iterator(); iter.hasNext(); index++) { + v = iter.next(); + if (sg.degreeOf(v) > 0) { + break; + } + } + + // Finds an arbitrary circuit of the current vertex and + // appends this into the circuit list + while (sg.degreeOf(v) > 0) { + for ( + Iterator iter = sg.vertexSet().iterator(); + iter.hasNext();) + { + V temp = iter.next(); + if (sg.containsEdge(v, temp)) { + path.add(index, temp); + sg.removeEdge(v, temp); + v = temp; + break; + } + } + } + } + return path; + } +} + +// End EulerianCircuit.java diff --git a/wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java b/wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java new file mode 100644 index 0000000..6e83410 --- /dev/null +++ b/wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java @@ -0,0 +1,317 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * FloydWarshallShortestPaths.java + * ------------------------- + * (C) Copyright 2009-2009, by Tom Larkworthy and Contributors + * + * Original Author: Tom Larkworthy + * Contributor(s): Soren Davidsen + * + * $Id: FloydWarshallShortestPaths.java 755 2012-01-18 23:50:37Z perfecthash $ + * + * Changes + * ------- + * 29-Jun-2009 : Initial revision (TL); + * 03-Dec-2009 : Optimized and enhanced version (SD); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; +import org.jgrapht.util.*; + + +/** + * The + * Floyd-Warshall algorithm finds all shortest paths (all n^2 of them) in + * O(n^3) time. It can also calculate the graph diameter. + * + * @author Tom Larkworthy + * @author Soren Davidsen + */ +public class FloydWarshallShortestPaths +{ + //~ Instance fields -------------------------------------------------------- + + private Graph graph; + private List vertices; + private int nShortestPaths = 0; + private double diameter = Double.NaN; + private double [][] d = null; + private int [][] backtrace = null; + private Map, GraphPath> paths = null; + + //~ Constructors ----------------------------------------------------------- + + public FloydWarshallShortestPaths(Graph graph) + { + this.graph = graph; + this.vertices = new ArrayList(graph.vertexSet()); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @return the graph on which this algorithm operates + */ + public Graph getGraph() + { + return graph; + } + + /** + * @return total number of shortest paths + */ + public int getShortestPathsCount() + { + lazyCalculatePaths(); + return nShortestPaths; + } + + /** + * Calculates the matrix of all shortest paths, but does not populate the + * paths map. + */ + private void lazyCalculateMatrix() + { + if (d != null) { + // already done + return; + } + + int n = vertices.size(); + + // init the backtrace matrix + backtrace = new int[n][n]; + for (int i = 0; i < n; i++) { + Arrays.fill(backtrace[i], -1); + } + + // initialize matrix, 0 + d = new double[n][n]; + for (int i = 0; i < n; i++) { + Arrays.fill(d[i], Double.POSITIVE_INFINITY); + } + + // initialize matrix, 1 + for (int i = 0; i < n; i++) { + d[i][i] = 0.0; + } + + // initialize matrix, 2 + Set edges = graph.edgeSet(); + for (E edge : edges) { + V v1 = graph.getEdgeSource(edge); + V v2 = graph.getEdgeTarget(edge); + + int v_1 = vertices.indexOf(v1); + int v_2 = vertices.indexOf(v2); + + d[v_1][v_2] = graph.getEdgeWeight(edge); + if (!(graph instanceof DirectedGraph)) { + d[v_2][v_1] = graph.getEdgeWeight(edge); + } + } + + // run fw alg + for (int k = 0; k < n; k++) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + double ik_kj = d[i][k] + d[k][j]; + if (ik_kj < d[i][j]) { + d[i][j] = ik_kj; + backtrace[i][j] = k; + } + } + } + } + } + + /** + * Get the length of a shortest path. + * + * @param a first vertex + * @param b second vertex + * + * @return shortest distance between a and b + */ + public double shortestDistance(V a, V b) + { + lazyCalculateMatrix(); + + return d[vertices.indexOf(a)][vertices.indexOf(b)]; + } + + /** + * @return the diameter (longest of all the shortest paths) computed for the + * graph. If the graph is vertexless, return 0.0. + */ + public double getDiameter() + { + lazyCalculateMatrix(); + + if (Double.isNaN(diameter)) { + diameter = 0.0; + int n = vertices.size(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (!Double.isInfinite(d[i][j]) && d[i][j] > diameter) { + diameter = d[i][j]; + } + } + } + } + return diameter; + } + + private void shortestPathRecur(List edges, int v_a, int v_b) + { + int k = backtrace[v_a][v_b]; + if (k == -1) { + E edge = graph.getEdge(vertices.get(v_a), vertices.get(v_b)); + if (edge != null) { + edges.add(edge); + } + } else { + shortestPathRecur(edges, v_a, k); + shortestPathRecur(edges, k, v_b); + } + } + + /** + * Get the shortest path between two vertices. Note: The paths are + * calculated using a recursive algorithm. It *will* give problems on paths + * longer than the stack allows. + * + * @param a From vertice + * @param b To vertice + * + * @return the path, or null if none found + */ + public GraphPath getShortestPath(V a, V b) + { + lazyCalculatePaths(); + return getShortestPathImpl(a, b); + } + + private GraphPath getShortestPathImpl(V a, V b) + { + int v_a = vertices.indexOf(a); + int v_b = vertices.indexOf(b); + + List edges = new ArrayList(); + shortestPathRecur(edges, v_a, v_b); + + // no path, return null + if (edges.size() < 1) { + return null; + } + + GraphPathImpl path = + new GraphPathImpl(graph, a, b, edges, edges.size()); + + return path; + } + + /** + * Calculate the shortest paths (not done per default) + */ + private void lazyCalculatePaths() + { + // already we have calculated it once. + if (paths != null) { + return; + } + + lazyCalculateMatrix(); + + Map, GraphPath> sps = + new HashMap, GraphPath>(); + int n = vertices.size(); + + nShortestPaths = 0; + for (int i = 0; i < n; i++) { + V v_i = vertices.get(i); + for (int j = 0; j < n; j++) { + // don't count this. + if (i == j) { + continue; + } + + V v_j = vertices.get(j); + + GraphPath path = getShortestPathImpl(v_i, v_j); + + // we got a path + if (path != null) { + sps.put(new VertexPair(v_i, v_j), path); + nShortestPaths++; + } + } + } + + this.paths = sps; + } + + /** + * Get shortest paths from a vertex to all other vertices in the graph. + * + * @param v the originating vertex + * + * @return List of paths + */ + public List> getShortestPaths(V v) + { + lazyCalculatePaths(); + List> found = new ArrayList>(); + + // TODO: two-level map for paths so that we don't have to + // iterate over all paths here! + for (VertexPair pair : paths.keySet()) { + if (pair.getFirst().equals(v)) { + found.add(paths.get(pair)); + } + } + + return found; + } + + /** + * Get all shortest paths in the graph. + * + * @return List of paths + */ + public Collection> getShortestPaths() + { + lazyCalculatePaths(); + return paths.values(); + } +} + +// End FloydWarshallShortestPaths.java diff --git a/wdl/org/jgrapht/alg/HamiltonianCycle.java b/wdl/org/jgrapht/alg/HamiltonianCycle.java new file mode 100644 index 0000000..0903f92 --- /dev/null +++ b/wdl/org/jgrapht/alg/HamiltonianCycle.java @@ -0,0 +1,120 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * HamiltonianCycle.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 17-Feb-2008 : Initial revision (AN); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.graph.*; + + +/** + * This class will deal with finding the optimal or approximately optimal + * minimum tour (hamiltonian cycle) or commonly known as the Traveling + * Salesman Problem. + * + * @author Andrew Newell + */ +public class HamiltonianCycle +{ + //~ Methods ---------------------------------------------------------------- + + /** + * This method will return an approximate minimal traveling salesman tour + * (hamiltonian cycle). This algorithm requires that the graph be complete + * and the triangle inequality exists (if x,y,z are vertices then + * d(x,y)+d(y,z) + * @param + * @param g is the graph to find the optimal tour for. + * + * @return The optimal tour as a list of vertices. + */ + public static List getApproximateOptimalForCompleteGraph( + SimpleWeightedGraph g) + { + List vertices = new LinkedList(g.vertexSet()); + + // If the graph is not complete then return null since this algorithm + // requires the graph be complete + if ((vertices.size() * (vertices.size() - 1) / 2) + != g.edgeSet().size()) + { + return null; + } + + List tour = new LinkedList(); + + // Each iteration a new vertex will be added to the tour until all + // vertices have been added + while (tour.size() != g.vertexSet().size()) { + boolean firstEdge = true; + double minEdgeValue = 0; + int minVertexFound = 0; + int vertexConnectedTo = 0; + + // A check will be made for the shortest edge to a vertex not within + // the tour and that new vertex will be added to the vertex + for (int i = 0; i < tour.size(); i++) { + V v = tour.get(i); + for (int j = 0; j < vertices.size(); j++) { + double weight = + g.getEdgeWeight(g.getEdge(v, vertices.get(j))); + if (firstEdge || (weight < minEdgeValue)) { + firstEdge = false; + minEdgeValue = weight; + minVertexFound = j; + vertexConnectedTo = i; + } + } + } + tour.add(vertexConnectedTo, vertices.get(minVertexFound)); + vertices.remove(minVertexFound); + } + return tour; + } +} + +// End HamiltonianCycle.java diff --git a/wdl/org/jgrapht/alg/KShortestPaths.java b/wdl/org/jgrapht/alg/KShortestPaths.java new file mode 100644 index 0000000..4e68251 --- /dev/null +++ b/wdl/org/jgrapht/alg/KShortestPaths.java @@ -0,0 +1,258 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * KShortestPaths.java + * ------------------------- + * (C) Copyright 2007-2010, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * 06-Dec-2010 : Bugfixes (GB); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * The algorithm determines the k shortest simple paths in increasing order of + * weight. Weights can be negative (but no negative cycle is allowed), and paths + * can be constrained by a maximum number of edges. Multigraphs are allowed. + * + *

The algorithm is a variant of the Bellman-Ford algorithm but instead of + * only storing the best path it stores the "k" best paths at each pass, + * yielding a complexity of O(k*n*(m^2)) where m is the number of edges and n is + * the number of vertices. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class KShortestPaths +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Graph on which shortest paths are searched. + */ + private Graph graph; + + private int nMaxHops; + + private int nPaths; + + private V startVertex; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates an object to compute ranking shortest paths between the start + * vertex and others vertices. + * + * @param graph + * @param startVertex + * @param k number of paths to be computed. + */ + public KShortestPaths(Graph graph, V startVertex, int k) + { + this(graph, startVertex, k, graph.vertexSet().size() - 1); + } + + /** + * Creates an object to calculate ranking shortest paths between the start + * vertex and others vertices. + * + * @param graph graph on which shortest paths are searched. + * @param startVertex start vertex of the calculated paths. + * @param nPaths number of ranking paths between the start vertex and an end + * vertex. + * @param nMaxHops maximum number of edges of the calculated paths. + * + * @throws NullPointerException if the specified graph or startVertex is + * null. + * @throws IllegalArgumentException if nPaths is negative or 0. + * @throws IllegalArgumentException if nMaxHops is negative or 0. + */ + public KShortestPaths( + Graph graph, + V startVertex, + int nPaths, + int nMaxHops) + { + assertKShortestPathsFinder(graph, startVertex, nPaths, nMaxHops); + + this.graph = graph; + this.startVertex = startVertex; + this.nPaths = nPaths; + this.nMaxHops = nMaxHops; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the k shortest simple paths in increasing order of weight. + * + * @param endVertex target vertex of the calculated paths. + * + * @return list of paths, or null if no path exists between the + * start vertex and the end vertex. + */ + public List> getPaths(V endVertex) + { + assertGetPaths(endVertex); + + KShortestPathsIterator iter = + new KShortestPathsIterator( + this.graph, + this.startVertex, + endVertex, + this.nPaths); + + // at the i-th pass the shortest paths with less (or equal) than i edges + // are calculated. + for ( + int passNumber = 1; + (passNumber <= this.nMaxHops) + && iter.hasNext(); + passNumber++) + { + iter.next(); + } + + List> list = iter.getPathElements(endVertex); + + if (list == null) { + return null; + } + + List> pathList = new ArrayList>(); + + for (RankingPathElement element : list) { + pathList.add(new PathWrapper(element)); + } + + return pathList; + } + + private void assertGetPaths(V endVertex) + { + if (endVertex == null) { + throw new NullPointerException("endVertex is null"); + } + if (endVertex.equals(this.startVertex)) { + throw new IllegalArgumentException( + "The end vertex is the same as the start vertex!"); + } + if (!this.graph.vertexSet().contains(endVertex)) { + throw new IllegalArgumentException( + "Graph must contain the end vertex!"); + } + } + + private void assertKShortestPathsFinder( + Graph graph, + V startVertex, + int nPaths, + int nMaxHops) + { + if (graph == null) { + throw new NullPointerException("graph is null"); + } + if (startVertex == null) { + throw new NullPointerException("startVertex is null"); + } + if (nPaths <= 0) { + throw new NullPointerException("nPaths is negative or 0"); + } + if (nMaxHops <= 0) { + throw new NullPointerException("nMaxHops is negative or 0"); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + private class PathWrapper + implements GraphPath + { + private RankingPathElement rankingPathElement; + + private List edgeList; + + PathWrapper(RankingPathElement rankingPathElement) + { + this.rankingPathElement = rankingPathElement; + } + + // implement GraphPath + public Graph getGraph() + { + return graph; + } + + // implement GraphPath + public V getStartVertex() + { + return startVertex; + } + + // implement GraphPath + public V getEndVertex() + { + return rankingPathElement.getVertex(); + } + + // implement GraphPath + public List getEdgeList() + { + if (edgeList == null) { + edgeList = rankingPathElement.createEdgeListPath(); + } + return edgeList; + } + + // implement GraphPath + public double getWeight() + { + return rankingPathElement.getWeight(); + } + + // override Object + public String toString() + { + return getEdgeList().toString(); + } + } +} + +// End KShortestPaths.java diff --git a/wdl/org/jgrapht/alg/KShortestPathsIterator.java b/wdl/org/jgrapht/alg/KShortestPathsIterator.java new file mode 100644 index 0000000..6dca6d1 --- /dev/null +++ b/wdl/org/jgrapht/alg/KShortestPathsIterator.java @@ -0,0 +1,416 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * KShortestPathsIterator.java + * ------------------------- + * (C) Copyright 2007-2010, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * 06-Dec-2010 : Bugfixes (GB); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Helper class for {@link KShortestPaths}. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +class KShortestPathsIterator + implements Iterator> +{ + //~ Instance fields -------------------------------------------------------- + + /** + * End vertex. + */ + private V endVertex; + + /** + * Graph on which shortest paths are searched. + */ + private Graph graph; + + /** + * Number of paths stored at each end vertex. + */ + private int k; + + /** + * Vertices whose ranking shortest paths have been modified during the + * previous pass. + */ + private Set prevImprovedVertices; + + /** + * Stores the paths that improved the vertex in the previous pass. + */ + private Map> prevSeenDataContainer; + + /** + * Stores the vertices that have been seen during iteration and (optionally) + * some additional traversal info regarding each vertex. Key = vertex, value + * = RankingPathElementList list of calculated paths. + */ + private Map> seenDataContainer; + + /** + * Start vertex. + */ + private V startVertex; + + private boolean startVertexEncountered; + + /** + * Stores the number of the path. + */ + private int passNumber = 1; + + //~ Constructors ----------------------------------------------------------- + + /** + * @param graph graph on which shortest paths are searched. + * @param startVertex start vertex of the calculated paths. + * @param endVertex end vertex of the calculated paths. + * @param maxSize number of paths stored at end vertex of the graph. + */ + public KShortestPathsIterator( + Graph graph, + V startVertex, + V endVertex, + int maxSize) + { + assertKShortestPathsIterator(graph, startVertex); + + this.graph = graph; + this.startVertex = startVertex; + this.endVertex = endVertex; + + this.k = maxSize; + + this.seenDataContainer = new HashMap>(); + this.prevSeenDataContainer = + new HashMap>(); + + this.prevImprovedVertices = new HashSet(); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @return true if at least one path has been improved during + * the previous pass, false otherwise. + */ + public boolean hasNext() + { + if (!this.startVertexEncountered) { + encounterStartVertex(); + } + + return !(this.prevImprovedVertices.isEmpty()); + } + + /** + * Returns the list of vertices whose path has been improved during the + * current pass. Complexity = + * + *

    + *
  • O(m*k*(m+n)) where k is the maximum number + * of shortest paths to compute, m is the number of edges of + * the graph and n is the number of vertices of the graph
  • + *
+ * + * @see java.util.Iterator#next() + */ + public Set next() + { + if (!this.startVertexEncountered) { + encounterStartVertex(); + } + + // at the i-th pass the shortest paths with i edges are calculated. + if (hasNext()) { + Set improvedVertices = new HashSet(); + + for ( + Iterator iter = this.prevImprovedVertices.iterator(); + iter.hasNext();) + { + V vertex = iter.next(); + if (!vertex.equals(this.endVertex)) { + updateOutgoingVertices(vertex, improvedVertices); + } + } + + savePassData(improvedVertices); + this.passNumber++; + + return improvedVertices; + } + throw new NoSuchElementException(); + } + + /** + * Unsupported. + * + * @see java.util.Iterator#remove() + */ + public void remove() + { + throw new UnsupportedOperationException(); + } + + /** + * Returns the path elements of the ranking shortest paths with less than + * nMaxHops edges between the start vertex and the end vertex. + * + * @param endVertex end vertex. + * + * @return list of RankingPathElement, or null of + * no path exists between the start vertex and the end vertex. + */ + RankingPathElementList getPathElements(V endVertex) + { + return this.seenDataContainer.get(endVertex); + } + + private void assertKShortestPathsIterator(Graph graph, V startVertex) + { + if (graph == null) { + throw new NullPointerException("graph is null"); + } + if (startVertex == null) { + throw new NullPointerException("startVertex is null"); + } + } + + /** + * The first time we see a vertex, make up a new entry for it. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + * + * @return the new entry. + */ + private RankingPathElementList createSeenData(V vertex, E edge) + { + V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); + + RankingPathElementList oppositeData = + this.prevSeenDataContainer.get(oppositeVertex); + + // endVertex in argument to ensure that stored paths do not disconnect + // the end-vertex + RankingPathElementList data = + new RankingPathElementList( + this.graph, + this.k, + oppositeData, + edge, + this.endVertex); + + return data; + } + + /** + * Returns an iterator to loop over outgoing edges Edge of the + * vertex. + * + * @param vertex + * + * @return . + */ + private Iterator edgesOfIterator(V vertex) + { + if (this.graph instanceof DirectedGraph) { + return ((DirectedGraph) this.graph).outgoingEdgesOf(vertex) + .iterator(); + } else { + return this.graph.edgesOf(vertex).iterator(); + } + } + + /** + * Initializes the list of paths at the start vertex and adds an empty path. + */ + private void encounterStartVertex() + { + RankingPathElementList data = + new RankingPathElementList( + this.graph, + this.k, + new RankingPathElement( + this.startVertex)); + + this.seenDataContainer.put(this.startVertex, data); + this.prevSeenDataContainer.put(this.startVertex, data); + + // initially the only vertex whose value is considered to have changed + // is the start vertex + this.prevImprovedVertices.add(this.startVertex); + + this.startVertexEncountered = true; + } + + private void savePassData(Set improvedVertices) + { + for (Iterator iter = improvedVertices.iterator(); iter.hasNext();) { + V vertex = iter.next(); + + RankingPathElementList pathElementList = + this.seenDataContainer.get(vertex); + + RankingPathElementList improvedPaths = + new RankingPathElementList( + this.graph, + pathElementList.maxSize, + vertex); + + for ( + Iterator> pathIter = + pathElementList.iterator(); + pathIter.hasNext();) + { + RankingPathElement path = pathIter.next(); + if (path.getHopCount() == this.passNumber) { + // the path has just been computed. + improvedPaths.pathElements.add(path); + } + } + + this.prevSeenDataContainer.put(vertex, improvedPaths); + } + + this.prevImprovedVertices = improvedVertices; + } + + /** + * Try to add the first paths to the specified vertex. These paths reached + * the specified vertex and ended with the specified edge. A new + * intermediary path is stored in the paths list of the specified vertex + * provided that the path can be extended to the end-vertex. + * + * @param vertex vertex reached by a path. + * @param edge edge reaching the vertex. + */ + private boolean tryToAddFirstPaths(V vertex, E edge) + { + // the vertex has not been reached yet + RankingPathElementList data = createSeenData(vertex, edge); + + if (!data.isEmpty()) { + this.seenDataContainer.put(vertex, data); + return true; + } + return false; + } + + /** + * Try to add new paths for the vertex. These new paths reached the + * specified vertex and ended with the specified edge. A new intermediary + * path is stored in the paths list of the specified vertex provided that + * the path can be extended to the end-vertex. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + */ + private boolean tryToAddNewPaths(V vertex, E edge) + { + RankingPathElementList data = this.seenDataContainer.get(vertex); + + V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); + RankingPathElementList oppositeData = + this.prevSeenDataContainer.get(oppositeVertex); + + return data.addPathElements(oppositeData, edge); + } + + /** + *

Updates outgoing vertices of the vertex. For each outgoing vertex, the + * new paths are obtained by concatenating the specified edge to the + * calculated paths of the specified vertex. If the weight of a new path is + * greater than the weight of any path stored so far at the outgoing vertex + * then the path is not added, otherwise it is added to the list of paths in + * increasing order of weight.

+ * + * Complexity = + * + *
    + *
  • O(d(v)*k*(m+n)) where d(v) is the outgoing + * degree of the specified vertex, k is the maximum number of + * shortest paths to compute, m is the number of edges of the + * graph and n is the number of vertices of the graph
  • + *
+ * + * @param vertex + * @param improvedVertices + */ + private void updateOutgoingVertices(V vertex, Set improvedVertices) + { + // try to add new paths for the target vertices of the outgoing edges + // of the vertex in argument. + for (Iterator iter = edgesOfIterator(vertex); iter.hasNext();) { + E edge = iter.next(); + V vertexReachedByEdge = + Graphs.getOppositeVertex(this.graph, edge, + vertex); + + // check if the path does not loop over the start vertex. + if (vertexReachedByEdge != this.startVertex) { + if (this.seenDataContainer.containsKey(vertexReachedByEdge)) { + boolean relaxed = + tryToAddNewPaths(vertexReachedByEdge, + edge); + if (relaxed) { + improvedVertices.add(vertexReachedByEdge); + } + } else { + boolean relaxed = + tryToAddFirstPaths(vertexReachedByEdge, + edge); + if (relaxed) { + improvedVertices.add(vertexReachedByEdge); + } + } + } + } + } +} + +// End KShortestPathsIterator.java diff --git a/wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java b/wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java new file mode 100644 index 0000000..574bb15 --- /dev/null +++ b/wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java @@ -0,0 +1,126 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * KruskalMinimumSpanningTree.java + * ------------------------- + * (C) Copyright 2010-2010, by Tom Conerly and Contributors. + * + * Original Author: Tom Conerly + * Contributor(s): + * + * Changes + * ------- + * 02-Feb-2010 : Initial revision (TC); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.util.*; + + +/** + * An implementation of Kruskal's minimum + * spanning tree algorithm. If the given graph is connected it computes the + * minimum spanning tree, otherwise it computes the minimum spanning forest. The + * algorithm runs in time O(E log E). This implementation uses the hashCode and + * equals method of the vertices. + * + * @author Tom Conerly + * @since Feb 10, 2010 + */ +public class KruskalMinimumSpanningTree +{ + //~ Instance fields -------------------------------------------------------- + + private double spanningTreeCost; + private Set edgeList; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates and executes a new KruskalMinimumSpanningTree algorithm instance. + * An instance is only good for a single spanning tree; after construction, + * it can be accessed to retrieve information about the spanning tree found. + * + * @param graph the graph to be searched + */ + public KruskalMinimumSpanningTree(final Graph graph) + { + UnionFind forest = new UnionFind(graph.vertexSet()); + ArrayList allEdges = new ArrayList(graph.edgeSet()); + Collections.sort( + allEdges, + new Comparator() { + public int compare(E edge1, E edge2) + { + return Double.valueOf(graph.getEdgeWeight(edge1)).compareTo( + graph.getEdgeWeight(edge2)); + } + }); + + spanningTreeCost = 0; + edgeList = new HashSet(); + + for (E edge : allEdges) { + V source = graph.getEdgeSource(edge); + V target = graph.getEdgeTarget(edge); + if (forest.find(source).equals(forest.find(target))) { + continue; + } + + forest.union(source, target); + edgeList.add(edge); + spanningTreeCost += graph.getEdgeWeight(edge); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the edges making up the tree found. + * + * @return Set of Edges + */ + public Set getEdgeSet() + { + return edgeList; + } + + /** + * Returns the cost of the minimum spanning tree or forest. + * + * @return Cost of the spanning tree + */ + public double getSpanningTreeCost() + { + return spanningTreeCost; + } +} + +// End KruskalMinimumSpanningTree.java diff --git a/wdl/org/jgrapht/alg/NeighborIndex.java b/wdl/org/jgrapht/alg/NeighborIndex.java new file mode 100644 index 0000000..36bfa82 --- /dev/null +++ b/wdl/org/jgrapht/alg/NeighborIndex.java @@ -0,0 +1,262 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * NeighborIndex.java + * -------------------------- + * (C) Copyright 2005-2008, by Charles Fry and Contributors. + * + * Original Author: Charles Fry + * + * $Id$ + * + * Changes + * ------- + * 13-Dec-2005 : Initial revision (CF); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; +import org.jgrapht.util.*; + + +/** + * Maintains a cache of each vertex's neighbors. While lists of neighbors can be + * obtained from {@link Graphs}, they are re-calculated at each invocation by + * walking a vertex's incident edges, which becomes inordinately expensive when + * performed often. + * + *

Edge direction is ignored when evaluating neighbors; to take edge + * direction into account when indexing neighbors, use {@link + * DirectedNeighborIndex}. + * + *

A vertex's neighbors are cached the first time they are asked for (i.e. + * the index is built on demand). The index will only be updated automatically + * if it is added to the associated graph as a listener. If it is added as a + * listener to a graph other than the one it indexes, results are undefined.

+ * + * @author Charles Fry + * @since Dec 13, 2005 + */ +public class NeighborIndex + implements GraphListener +{ + //~ Instance fields -------------------------------------------------------- + + Map> neighborMap = new HashMap>(); + private Graph graph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a neighbor index for the specified undirected graph. + * + * @param g the graph for which a neighbor index is to be created. + */ + public NeighborIndex(Graph g) + { + // no need to distinguish directedgraphs as we don't do traversals + graph = g; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the set of vertices which are adjacent to a specified vertex. The + * returned set is backed by the index, and will be updated when the graph + * changes as long as the index has been added as a listener to the graph. + * + * @param v the vertex whose neighbors are desired + * + * @return all unique neighbors of the specified vertex + */ + public Set neighborsOf(V v) + { + return getNeighbors(v).getNeighbors(); + } + + /** + * Returns a list of vertices which are adjacent to a specified vertex. If + * the graph is a multigraph, vertices may appear more than once in the + * returned list. Because a list of neighbors can not be efficiently + * maintained, it is reconstructed on every invocation, by duplicating + * entries in the neighbor set. It is thus more efficient to use {@link + * #neighborsOf(Object)} unless duplicate neighbors are important. + * + * @param v the vertex whose neighbors are desired + * + * @return all neighbors of the specified vertex + */ + public List neighborListOf(V v) + { + return getNeighbors(v).getNeighborList(); + } + + /** + * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) + */ + public void edgeAdded(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + V source = graph.getEdgeSource(edge); + V target = graph.getEdgeTarget(edge); + + // if a map does not already contain an entry, + // then skip addNeighbor, since instantiating the map + // will take care of processing the edge (which has already + // been added) + + if (neighborMap.containsKey(source)) { + getNeighbors(source).addNeighbor(target); + } else { + getNeighbors(source); + } + if (neighborMap.containsKey(target)) { + getNeighbors(target).addNeighbor(source); + } else { + getNeighbors(target); + } + } + + /** + * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) + */ + public void edgeRemoved(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + V source = e.getEdgeSource(); + V target = e.getEdgeTarget(); + if (neighborMap.containsKey(source)) { + neighborMap.get(source).removeNeighbor(target); + } + if (neighborMap.containsKey(target)) { + neighborMap.get(target).removeNeighbor(source); + } + } + + /** + * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) + */ + public void vertexAdded(GraphVertexChangeEvent e) + { + // nothing to cache until there are edges + } + + /** + * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) + */ + public void vertexRemoved(GraphVertexChangeEvent e) + { + neighborMap.remove(e.getVertex()); + } + + private Neighbors getNeighbors(V v) + { + Neighbors neighbors = neighborMap.get(v); + if (neighbors == null) { + neighbors = new Neighbors(v, + Graphs.neighborListOf(graph, v)); + neighborMap.put(v, neighbors); + } + return neighbors; + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Stores cached neighbors for a single vertex. Includes support for live + * neighbor sets and duplicate neighbors. + */ + static class Neighbors + { + private Map neighborCounts = + new LinkedHashMap(); + + // TODO could eventually make neighborSet modifiable, resulting + // in edge removals from the graph + private Set neighborSet = + Collections.unmodifiableSet( + neighborCounts.keySet()); + + public Neighbors(V v, Collection neighbors) + { + // add all current neighbors + for (V neighbor : neighbors) { + addNeighbor(neighbor); + } + } + + public void addNeighbor(V v) + { + ModifiableInteger count = neighborCounts.get(v); + if (count == null) { + count = new ModifiableInteger(1); + neighborCounts.put(v, count); + } else { + count.increment(); + } + } + + public void removeNeighbor(V v) + { + ModifiableInteger count = neighborCounts.get(v); + if (count == null) { + throw new IllegalArgumentException( + "Attempting to remove a neighbor that wasn't present"); + } + + count.decrement(); + if (count.getValue() == 0) { + neighborCounts.remove(v); + } + } + + public Set getNeighbors() + { + return neighborSet; + } + + public List getNeighborList() + { + List neighbors = new ArrayList(); + for ( + Map.Entry entry + : neighborCounts.entrySet()) + { + V v = entry.getKey(); + int count = entry.getValue().intValue(); + for (int i = 0; i < count; i++) { + neighbors.add(v); + } + } + return neighbors; + } + } +} + +// End NeighborIndex.java diff --git a/wdl/org/jgrapht/alg/RankingPathElement.java b/wdl/org/jgrapht/alg/RankingPathElement.java new file mode 100644 index 0000000..0ee3047 --- /dev/null +++ b/wdl/org/jgrapht/alg/RankingPathElement.java @@ -0,0 +1,115 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * RankingPathElement.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * + */ +package org.jgrapht.alg; + +import org.jgrapht.*; + + +/** + * Helper class for {@link KShortestPaths}. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +final class RankingPathElement + extends AbstractPathElement +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Weight of the path. + */ + private double weight; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a path element by concatenation of an edge to a path element. + * + * @param pathElement + * @param edge edge reaching the end vertex of the path element created. + * @param weight total cost of the created path element. + */ + RankingPathElement( + Graph graph, + RankingPathElement pathElement, + E edge, + double weight) + { + super(graph, pathElement, edge); + this.weight = weight; + } + + /** + * Creates an empty path element. + * + * @param vertex end vertex of the path element. + */ + RankingPathElement(V vertex) + { + super(vertex); + this.weight = 0; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the weight of the path. + * + * @return . + */ + public double getWeight() + { + return this.weight; + } + + /** + * Returns the previous path element. + * + * @return null is the path is empty. + */ + public RankingPathElement getPrevPathElement() + { + return (RankingPathElement) super.getPrevPathElement(); + } +} + +// End RankingPathElement.java diff --git a/wdl/org/jgrapht/alg/RankingPathElementList.java b/wdl/org/jgrapht/alg/RankingPathElementList.java new file mode 100644 index 0000000..532fcc7 --- /dev/null +++ b/wdl/org/jgrapht/alg/RankingPathElementList.java @@ -0,0 +1,436 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * RankingPathElementList.java + * ------------------------- + * (C) Copyright 2007-2010, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * 05-Jul-2007 : Added support for generics (JVS); + * 06-Dec-2010 : Bugfixes (GB); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + * List of simple paths in increasing order of weight. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +final class RankingPathElementList + extends AbstractPathElementList> +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Vertex that paths of the list must not disconnect. + */ + private V guardVertexToNotDisconnect = null; + + private Map, Boolean> path2disconnect = + new HashMap, Boolean>(); + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a list with an empty path. The list size is 1. + * + * @param maxSize max number of paths the list is able to store. + */ + RankingPathElementList( + Graph graph, + int maxSize, + RankingPathElement pathElement) + { + super(graph, maxSize, pathElement); + } + + /** + * Creates paths obtained by concatenating the specified edge to the + * specified paths. + * + * @param prevPathElementList paths, list of + * RankingPathElement. + * @param edge edge reaching the end vertex of the created paths. + * @param maxSize maximum number of paths the list is able to store. + */ + RankingPathElementList( + Graph graph, + int maxSize, + RankingPathElementList elementList, + E edge) + { + this(graph, maxSize, elementList, edge, null); + + assert (!this.pathElements.isEmpty()); + } + + /** + * Creates paths obtained by concatenating the specified edge to the + * specified paths. + * + * @param prevPathElementList paths, list of + * RankingPathElement. + * @param edge edge reaching the end vertex of the created paths. + * @param maxSize maximum number of paths the list is able to store. + */ + RankingPathElementList( + Graph graph, + int maxSize, + RankingPathElementList elementList, + E edge, + V guardVertexToNotDisconnect) + { + super(graph, maxSize, elementList, edge); + this.guardVertexToNotDisconnect = guardVertexToNotDisconnect; + + // loop over the path elements in increasing order of weight. + for (int i = 0; i < elementList.size(); i++) { + RankingPathElement prevPathElement = elementList.get(i); + + if (isNotValidPath(prevPathElement, edge)) { + continue; + } + + if (size() < this.maxSize) { + double weight = calculatePathWeight(prevPathElement, edge); + RankingPathElement newPathElement = + new RankingPathElement( + this.graph, + prevPathElement, + edge, + weight); + + // the new path is inserted at the end of the list. + this.pathElements.add(newPathElement); + } + } + } + + /** + * Creates an empty list. The list size is 0. + * + * @param maxSize max number of paths the list is able to store. + */ + RankingPathElementList(Graph graph, int maxSize, V vertex) + { + super(graph, maxSize, vertex); + } + + //~ Methods ---------------------------------------------------------------- + + /** + *

Adds paths in the list at vertex y. Candidate paths are obtained by + * concatenating the specified edge (v->y) to the paths + * elementList at vertex v.

+ * + * Complexity = + * + *
    + *
  • w/o guard-vertex: O(k*np) where k is the + * max size limit of the list and np is the maximum number of + * vertices in the paths stored in the list
  • + *
  • with guard-vertex: O(k*(m+n)) where k is + * the max size limit of the list, m is the number of edges of + * the graph and n is the number of vertices of the graph, + * O(m+n) being the complexity of the + * ConnectivityInspector to check whether a path exists towards the + * guard-vertex
  • + *
+ * + * @param elementList list of paths at vertex v. + * @param edge edge (v->y). + * + * @return true if at least one path has been added in the + * list, false otherwise. + */ + public boolean addPathElements( + RankingPathElementList elementList, + E edge) + { + assert (this.vertex.equals( + Graphs.getOppositeVertex( + this.graph, + edge, + elementList.getVertex()))); + + boolean pathAdded = false; + + // loop over the paths elements of the list at vertex v. + for ( + int vIndex = 0, yIndex = 0; + vIndex < elementList.size(); + vIndex++) + { + RankingPathElement prevPathElement = elementList.get(vIndex); + + if (isNotValidPath(prevPathElement, edge)) { + // checks if path is simple and if guard-vertex is not + // disconnected. + continue; + } + double newPathWeight = calculatePathWeight(prevPathElement, edge); + RankingPathElement newPathElement = + new RankingPathElement( + this.graph, + prevPathElement, + edge, + newPathWeight); + + // loop over the paths of the list at vertex y from yIndex to the + // end. + RankingPathElement yPathElement = null; + for (; yIndex < size(); yIndex++) { + yPathElement = get(yIndex); + + // case when the new path is shorter than the path Py stored at + // index y + if (newPathWeight < yPathElement.getWeight()) { + this.pathElements.add(yIndex, newPathElement); + pathAdded = true; + + // ensures max size limit is not exceeded. + if (size() > this.maxSize) { + this.pathElements.remove(this.maxSize); + } + break; + } + + // case when the new path is of the same length as the path Py + // stored at index y + if (newPathWeight == yPathElement.getWeight()) { + this.pathElements.add(yIndex + 1, newPathElement); + pathAdded = true; + + // ensures max size limit is not exceeded. + if (size() > this.maxSize) { + this.pathElements.remove(this.maxSize); + } + break; + } + } + + // case when the new path is longer than the longest path in the + // list (Py stored at the last index y) + if (newPathWeight > yPathElement.getWeight()) { + // ensures max size limit is not exceeded. + if (size() < this.maxSize) { + // the new path is inserted at the end of the list. + this.pathElements.add(newPathElement); + pathAdded = true; + } else { + // max size limit is reached -> end of the loop over the + // paths elements of the list at vertex v. + break; + } + } + } + + return pathAdded; + } + + /** + * @return list of RankingPathElement. + */ + List> getPathElements() + { + return this.pathElements; + } + + /** + * Costs taken into account are the weights stored in Edge + * objects. + * + * @param pathElement + * @param edge the edge via which the vertex was encountered. + * + * @return the cost obtained by concatenation. + * + * @see Graph#getEdgeWeight(E) + */ + private double calculatePathWeight( + RankingPathElement pathElement, + E edge) + { + double pathWeight = this.graph.getEdgeWeight(edge); + + // otherwise it's the start vertex. + if ((pathElement.getPrevEdge() != null)) { + pathWeight += pathElement.getWeight(); + } + + return pathWeight; + } + + /** + * Ensures that paths of the list do not disconnect the guard-vertex. + * + * @return true if the specified path element disconnects the + * guard-vertex, false otherwise. + */ + private boolean isGuardVertexDisconnected( + RankingPathElement prevPathElement) + { + if (this.guardVertexToNotDisconnect == null) { + return false; + } + + if (this.path2disconnect.containsKey(prevPathElement)) { + return this.path2disconnect.get(prevPathElement); + } + + ConnectivityInspector connectivityInspector; + MaskFunctor connectivityMask; + + if (this.graph instanceof DirectedGraph) { + connectivityMask = new PathMask(prevPathElement); + DirectedMaskSubgraph connectivityGraph = + new DirectedMaskSubgraph( + (DirectedGraph) this.graph, + connectivityMask); + connectivityInspector = + new ConnectivityInspector( + connectivityGraph); + } else { + connectivityMask = new PathMask(prevPathElement); + UndirectedMaskSubgraph connectivityGraph = + new UndirectedMaskSubgraph( + (UndirectedGraph) this.graph, + connectivityMask); + connectivityInspector = + new ConnectivityInspector( + connectivityGraph); + } + + if (connectivityMask.isVertexMasked(this.guardVertexToNotDisconnect)) { + // the guard-vertex was already in the path element -> invalid path + this.path2disconnect.put(prevPathElement, true); + return true; + } + + if (!connectivityInspector.pathExists( + this.vertex, + this.guardVertexToNotDisconnect)) + { + this.path2disconnect.put(prevPathElement, true); + return true; + } + + this.path2disconnect.put(prevPathElement, false); + return false; + } + + private boolean isNotValidPath( + RankingPathElement prevPathElement, + E edge) + { + return !isSimplePath(prevPathElement, edge) + || isGuardVertexDisconnected(prevPathElement); + } + + /** + * Ensures that paths of the list are simple (check that the vertex was not + * already in the path element). + * + * @param prevPathElement + * @param edge + * + * @return true if the resulting path (obtained by + * concatenating the specified edge to the specified path) is simple, + * false otherwise. + */ + private boolean isSimplePath( + RankingPathElement prevPathElement, + E edge) + { + RankingPathElement pathElementToTest = prevPathElement; + while (pathElementToTest.getPrevEdge() != null) { + if (pathElementToTest.getVertex() == this.vertex) { + return false; + } else { + pathElementToTest = pathElementToTest.getPrevPathElement(); + } + } + + return true; + } + + //~ Inner Classes ---------------------------------------------------------- + + private static class PathMask + implements MaskFunctor + { + private Set maskedEdges; + + private Set maskedVertices; + + /** + * Creates a mask for all the edges and the vertices of the path + * (including the 2 extremity vertices). + * + * @param pathElement + */ + PathMask(RankingPathElement pathElement) + { + this.maskedEdges = new HashSet(); + this.maskedVertices = new HashSet(); + + while (pathElement.getPrevEdge() != null) { + this.maskedEdges.add(pathElement.getPrevEdge()); + this.maskedVertices.add(pathElement.getVertex()); + pathElement = pathElement.getPrevPathElement(); + } + this.maskedVertices.add(pathElement.getVertex()); + } + + // implement MaskFunctor + public boolean isEdgeMasked(E edge) + { + return this.maskedEdges.contains(edge); + } + + // implement MaskFunctor + public boolean isVertexMasked(V vertex) + { + return this.maskedVertices.contains(vertex); + } + } +} + +// End RankingPathElementList.java diff --git a/wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java b/wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java new file mode 100644 index 0000000..3fecb74 --- /dev/null +++ b/wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java @@ -0,0 +1,283 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2011, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * StoerWagnerMinimumCut.java + * ---------------- + * (C) Copyright 2011-2011, by Robby McKilliam and Contributors. + * + * Original Author: Robby McKilliam + * Contributor(s): - + * + * $Id: StoerWagnerMinimumCut.java $ + * + * Changes + * ------- + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; +import org.jgrapht.util.*; + + +/** + * Implements the Stoer and + * Wagner minimum cut algorithm. Deterministically computes the minimum cut + * in O(|V||E| + |V|log|V|) time. This implementation uses Java's PriorityQueue + * and requires O(|V||E|log|E|) time. M. Stoer and F. Wagner, "A Simple Min-Cut + * Algorithm", Journal of the ACM, volume 44, number 4. pp 585-591, 1997. + * + * @author Robby McKilliam + */ +public class StoerWagnerMinimumCut +{ + //~ Instance fields -------------------------------------------------------- + + final WeightedGraph, DefaultWeightedEdge> workingGraph; + + double bestcutweight = Double.POSITIVE_INFINITY; + Set bestCut; + + boolean firstRun = true; + + //~ Constructors ----------------------------------------------------------- + + /** + * Will compute the minimum cut in graph. + * + * @param graph graph over which to run algorithm + */ + public StoerWagnerMinimumCut(WeightedGraph graph) + { + //get a version of this graph where each vertex is wrapped with a list + workingGraph = + new SimpleWeightedGraph, DefaultWeightedEdge>( + DefaultWeightedEdge.class); + Map> vertexMap = new HashMap>(); + for (V v : graph.vertexSet()) { + Set list = new HashSet(); + list.add(v); + vertexMap.put(v, list); + workingGraph.addVertex(list); + } + for (E e : graph.edgeSet()) { + V s = graph.getEdgeSource(e); + Set sNew = vertexMap.get(s); + V t = graph.getEdgeTarget(e); + Set tNew = vertexMap.get(t); + DefaultWeightedEdge eNew = workingGraph.addEdge(sNew, tNew); + workingGraph.setEdgeWeight(eNew, graph.getEdgeWeight(e)); + } + + //arbitrary vertex used to seed the algorithm. + Set a = workingGraph.vertexSet().iterator().next(); + while (workingGraph.vertexSet().size() > 2) { + minimumCutPhase(a); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Implements the MinimumCutPhase function of Stoer and Wagner + */ + protected void minimumCutPhase(Set a) + { + //construct sorted queue with vertices connected to vertex a + PriorityQueue queue = + new PriorityQueue(); + Map, VertexAndWeight> dmap = + new HashMap, VertexAndWeight>(); + for (Set v : workingGraph.vertexSet()) { + if (v != a) { + Double w = + -workingGraph.getEdgeWeight(workingGraph.getEdge(v, a)); + VertexAndWeight vandw = new VertexAndWeight(v, w); + queue.add(vandw); + dmap.put(v, vandw); + } + } + + //now iteratatively update the queue to get the required vertex ordering + List> list = + new ArrayList>(workingGraph.vertexSet().size()); + list.add(a); + while (!queue.isEmpty()) { + Set v = queue.poll().vertex; + dmap.remove(v); + list.add(v); + for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) { + Set vc; + if (v != workingGraph.getEdgeSource(e)) { + vc = workingGraph.getEdgeSource(e); + } else { + vc = workingGraph.getEdgeTarget(e); + } + if (dmap.get(vc) != null) { + Double neww = + -workingGraph.getEdgeWeight(workingGraph.getEdge(v, vc)) + + dmap.get(vc).weight; + queue.remove(dmap.get(vc)); //this is O(logn) but could be + //O(1)? + dmap.get(vc).weight = neww; + queue.add(dmap.get(vc)); //this is O(logn) but could be + //O(1)? + } + } + } + + //if this is the first run we compute the weight of last vertex in the + //list + if (firstRun) { + Set v = list.get(list.size() - 1); + double w = vertexWeight(v); + if (w < bestcutweight) { + bestcutweight = w; + bestCut = v; + } + firstRun = false; + } + + //the last two elements in list are the vertices we want to merge. + Set s = list.get(list.size() - 2); + Set t = list.get(list.size() - 1); + + //merge these vertices and get the weight. + VertexAndWeight vw = mergeVertices(s, t); + + //If this is the best cut so far store it. + if (vw.weight < bestcutweight) { + bestcutweight = vw.weight; + bestCut = vw.vertex; + } + } + + /** + * Return the weight of the minimum cut + */ + public double minCutWeight() + { + return bestcutweight; + } + + /** + * Return a set of vertices on one side of the cut + */ + public Set minCut() + { + return bestCut; + } + + /** + * Merges vertex t into vertex s, summing the weights as required. Returns + * the merged vertex and the sum of its weights + */ + protected VertexAndWeight mergeVertices(Set s, Set t) + { + //construct the new combinedvertex + Set set = new HashSet(); + for (V v : s) { + set.add(v); + } + for (V v : t) { + set.add(v); + } + workingGraph.addVertex(set); + + //add edges and weights to the combined vertex + double wsum = 0.0; + for (Set v : workingGraph.vertexSet()) { + if ((s != v) && (t != v)) { + DefaultWeightedEdge etv = workingGraph.getEdge(t, v); + DefaultWeightedEdge esv = workingGraph.getEdge(s, v); + double wtv = 0.0, wsv = 0.0; + if (etv != null) { + wtv = workingGraph.getEdgeWeight(etv); + } + if (esv != null) { + wsv = workingGraph.getEdgeWeight(esv); + } + double neww = wtv + wsv; + wsum += neww; + if (neww != 0.0) { + workingGraph.setEdgeWeight( + workingGraph.addEdge(set, v), + neww); + } + } + } + + //remove original vertices + workingGraph.removeVertex(t); + workingGraph.removeVertex(s); + + return new VertexAndWeight(set, wsum); + } + + /** + * Compute the sum of the weights entering a vertex + */ + public double vertexWeight(Set v) + { + double wsum = 0.0; + for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) { + wsum += workingGraph.getEdgeWeight(e); + } + return wsum; + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Class for weighted vertices + */ + protected class VertexAndWeight + implements Comparable + { + public Set vertex; + public Double weight; + + public VertexAndWeight(Set v, double w) + { + this.vertex = v; + this.weight = w; + } + + @Override public int compareTo(VertexAndWeight that) + { + return Double.compare(weight, that.weight); + } + + @Override public String toString() + { + return "(" + vertex + ", " + weight + ")"; + } + } +} + +// End StoerWagnerMinimumCut.java diff --git a/wdl/org/jgrapht/alg/StrongConnectivityInspector.java b/wdl/org/jgrapht/alg/StrongConnectivityInspector.java new file mode 100644 index 0000000..2dd92ed --- /dev/null +++ b/wdl/org/jgrapht/alg/StrongConnectivityInspector.java @@ -0,0 +1,393 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * StrongConnectivityInspector.java + * -------------------------- + * (C) Copyright 2005-2008, by Christian Soltenborn and Contributors. + * + * Original Author: Christian Soltenborn + * + * $Id$ + * + * Changes + * ------- + * 2-Feb-2005 : Initial revision (CS); + * 5-Feb-2007 : fixed NullPointerException (CS); + * 1-Apr-2008 : Reduced memory consumption (CS); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + *

Complements the {@link org.jgrapht.alg.ConnectivityInspector} class with + * the capability to compute the strongly connected components of a directed + * graph. The algorithm is implemented after "Cormen et al: Introduction to + * agorithms", Chapter 22.5. It has a running time of O(V + E).

+ * + *

Unlike {@link org.jgrapht.alg.ConnectivityInspector}, this class does not + * implement incremental inspection. The full algorithm is executed at the first + * call of {@link StrongConnectivityInspector#stronglyConnectedSets()} or {@link + * StrongConnectivityInspector#isStronglyConnected()}.

+ * + * @author Christian Soltenborn + * @author Christian Hammer + * @since Feb 2, 2005 + */ +public class StrongConnectivityInspector +{ + //~ Instance fields -------------------------------------------------------- + + // the graph to compute the strongly connected sets for + private final DirectedGraph graph; + + // stores the vertices, ordered by their finishing time in first dfs + private LinkedList> orderedVertices; + + // the result of the computation, cached for future calls + private List> stronglyConnectedSets; + + // the result of the computation, cached for future calls + private List> stronglyConnectedSubgraphs; + + // maps vertices to their VertexData object + private Map> vertexToVertexData; + + //~ Constructors ----------------------------------------------------------- + + /** + * The constructor of the StrongConnectivityInspector class. + * + * @param directedGraph the graph to inspect + * + * @throws IllegalArgumentException + */ + public StrongConnectivityInspector(DirectedGraph directedGraph) + { + if (directedGraph == null) { + throw new IllegalArgumentException("null not allowed for graph!"); + } + + graph = directedGraph; + vertexToVertexData = null; + orderedVertices = null; + stronglyConnectedSets = null; + stronglyConnectedSubgraphs = null; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the graph inspected by the StrongConnectivityInspector. + * + * @return the graph inspected by this StrongConnectivityInspector + */ + public DirectedGraph getGraph() + { + return graph; + } + + /** + * Returns true if the graph of this + * StronglyConnectivityInspector instance is strongly connected. + * + * @return true if the graph is strongly connected, false otherwise + */ + public boolean isStronglyConnected() + { + return stronglyConnectedSets().size() == 1; + } + + /** + * Computes a {@link List} of {@link Set}s, where each set contains vertices + * which together form a strongly connected component within the given + * graph. + * + * @return List of Set s containing the strongly + * connected components + */ + public List> stronglyConnectedSets() + { + if (stronglyConnectedSets == null) { + orderedVertices = new LinkedList>(); + stronglyConnectedSets = new Vector>(); + + // create VertexData objects for all vertices, store them + createVertexData(); + + // perform the first round of DFS, result is an ordering + // of the vertices by decreasing finishing time + for (VertexData data : vertexToVertexData.values()) { + if (!data.isDiscovered()) { + dfsVisit(graph, data, null); + } + } + + // 'create' inverse graph (i.e. every edge is reversed) + DirectedGraph inverseGraph = + new EdgeReversedGraph(graph); + + // get ready for next dfs round + resetVertexData(); + + // second dfs round: vertices are considered in decreasing + // finishing time order; every tree found is a strongly + // connected set + for (VertexData data : orderedVertices) { + if (!data.isDiscovered()) { + // new strongly connected set + Set set = new HashSet(); + stronglyConnectedSets.add(set); + dfsVisit(inverseGraph, data, set); + } + } + + // clean up for garbage collection + orderedVertices = null; + vertexToVertexData = null; + } + + return stronglyConnectedSets; + } + + /** + *

Computes a list of {@link DirectedSubgraph}s of the given graph. Each + * subgraph will represent a strongly connected component and will contain + * all vertices of that component. The subgraph will have an edge (u,v) iff + * u and v are contained in the strongly connected component.

+ * + *

NOTE: Calling this method will first execute {@link + * StrongConnectivityInspector#stronglyConnectedSets()}. If you don't need + * subgraphs, use that method.

+ * + * @return a list of subgraphs representing the strongly connected + * components + */ + public List> stronglyConnectedSubgraphs() + { + if (stronglyConnectedSubgraphs == null) { + List> sets = stronglyConnectedSets(); + stronglyConnectedSubgraphs = + new Vector>(sets.size()); + + for (Set set : sets) { + stronglyConnectedSubgraphs.add( + new DirectedSubgraph( + graph, + set, + null)); + } + } + + return stronglyConnectedSubgraphs; + } + + /* + * Creates a VertexData object for every vertex in the graph and stores + * them + * in a HashMap. + */ + private void createVertexData() + { + vertexToVertexData = + new HashMap>(graph.vertexSet().size()); + + for (V vertex : graph.vertexSet()) { + vertexToVertexData.put( + vertex, + new VertexData2(vertex, false, false)); + } + } + + /* + * The subroutine of DFS. NOTE: the set is used to distinguish between 1st + * and 2nd round of DFS. set == null: finished vertices are stored (1st + * round). set != null: all vertices found will be saved in the set (2nd + * round) + */ + private void dfsVisit( + DirectedGraph visitedGraph, + VertexData vertexData, + Set vertices) + { + Deque> stack = new ArrayDeque>(); + stack.add(vertexData); + + while (!stack.isEmpty()) { + VertexData data = stack.removeLast(); + + if (!data.isDiscovered()) { + data.setDiscovered(true); + + if (vertices != null) { + vertices.add(data.getVertex()); + } + + stack.add(new VertexData1(data, true, true)); + + // follow all edges + for (E edge : visitedGraph.outgoingEdgesOf(data.getVertex())) { + VertexData targetData = + vertexToVertexData.get( + visitedGraph.getEdgeTarget(edge)); + + if (!targetData.isDiscovered()) { + // the "recursion" + stack.add(targetData); + } + } + } else if (data.isFinished()) { + if (vertices == null) { + orderedVertices.addFirst(data.getFinishedData()); + } + } + } + } + + /* + * Resets all VertexData objects. + */ + private void resetVertexData() + { + for (VertexData data : vertexToVertexData.values()) { + data.setDiscovered(false); + data.setFinished(false); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + /* + * Lightweight class storing some data for every vertex. + */ + private static abstract class VertexData + { + private byte bitfield; + + private VertexData( + boolean discovered, + boolean finished) + { + this.bitfield = 0; + setDiscovered(discovered); + setFinished(finished); + } + + private boolean isDiscovered() + { + if ((bitfield & 1) == 1) { + return true; + } + return false; + } + + private boolean isFinished() + { + if ((bitfield & 2) == 2) { + return true; + } + return false; + } + + private void setDiscovered(boolean discovered) + { + if (discovered) { + bitfield |= 1; + } else { + bitfield &= ~1; + } + } + + private void setFinished(boolean finished) + { + if (finished) { + bitfield |= 2; + } else { + bitfield &= ~2; + } + } + + abstract VertexData getFinishedData(); + + abstract V getVertex(); + } + + private static final class VertexData1 + extends VertexData + { + private final VertexData finishedData; + + private VertexData1( + VertexData finishedData, + boolean discovered, + boolean finished) + { + super(discovered, finished); + this.finishedData = finishedData; + } + + VertexData getFinishedData() + { + return finishedData; + } + + V getVertex() + { + return null; + } + } + + private static final class VertexData2 + extends VertexData + { + private final V vertex; + + private VertexData2( + V vertex, + boolean discovered, + boolean finished) + { + super(discovered, finished); + this.vertex = vertex; + } + + VertexData getFinishedData() + { + return null; + } + + V getVertex() + { + return vertex; + } + } +} + +// End StrongConnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/TransitiveClosure.java b/wdl/org/jgrapht/alg/TransitiveClosure.java new file mode 100644 index 0000000..4f70b13 --- /dev/null +++ b/wdl/org/jgrapht/alg/TransitiveClosure.java @@ -0,0 +1,138 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * TransitiveClosure.java + * ---------------------- + * (C) Copyright 2007, by Vinayak R. Borkar. + * + * Original Author: Vinayak R. Borkar + * Contributor(s): + * + * Changes + * ------- + * 5-May-2007: Initial revision (VRB); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.graph.*; + + +/** + * Constructs the transitive closure of the input graph. + * + * @author Vinayak R. Borkar + * @since May 5, 2007 + */ +public class TransitiveClosure +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Singleton instance. + */ + public static final TransitiveClosure INSTANCE = new TransitiveClosure(); + + //~ Constructors ----------------------------------------------------------- + + /** + * Private Constructor. + */ + private TransitiveClosure() + { + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Computes the transitive closure of the given graph. + * + * @param graph - Graph to compute transitive closure for. + */ + public void closeSimpleDirectedGraph(SimpleDirectedGraph graph) + { + Set vertexSet = graph.vertexSet(); + + Set newEdgeTargets = new HashSet(); + + // At every iteration of the outer loop, we add a path of length 1 + // between nodes that originally had a path of length 2. In the worst + // case, we need to make floor(log |V|) + 1 iterations. We stop earlier + // if there is no change to the output graph. + + int bound = computeBinaryLog(vertexSet.size()); + boolean done = false; + for (int i = 0; !done && (i < bound); ++i) { + done = true; + for (V v1 : vertexSet) { + newEdgeTargets.clear(); + + for (E v1OutEdge : graph.outgoingEdgesOf(v1)) { + V v2 = graph.getEdgeTarget(v1OutEdge); + for (E v2OutEdge : graph.outgoingEdgesOf(v2)) { + V v3 = graph.getEdgeTarget(v2OutEdge); + + if (v1.equals(v3)) { + // Its a simple graph, so no self loops. + continue; + } + + if (graph.getEdge(v1, v3) != null) { + // There is already an edge from v1 ---> v3, skip; + continue; + } + + newEdgeTargets.add(v3); + done = false; + } + } + + for (V v3 : newEdgeTargets) { + graph.addEdge(v1, v3); + } + } + } + } + + /** + * Computes floor(log_2(n)) + 1 + */ + private int computeBinaryLog(int n) + { + assert n >= 0; + + int result = 0; + while (n > 0) { + n >>= 1; + ++result; + } + + return result; + } +} + +// End TransitiveClosure.java diff --git a/wdl/org/jgrapht/alg/VertexCovers.java b/wdl/org/jgrapht/alg/VertexCovers.java new file mode 100644 index 0000000..71a5240 --- /dev/null +++ b/wdl/org/jgrapht/alg/VertexCovers.java @@ -0,0 +1,157 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * VertexCovers.java + * ----------------- + * (C) Copyright 2003-2008, by Linda Buisman and Contributors. + * + * Original Author: Linda Buisman + * Contributor(s): Barak Naveh + * Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 06-Nov-2003 : Initial revision (LB); + * 07-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.alg; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.util.*; +import org.jgrapht.graph.*; + + +/** + * Algorithms to find a vertex cover for a graph. A vertex cover is a set of + * vertices that touches all the edges in the graph. The graph's vertex set is a + * trivial cover. However, a minimal vertex set (or at least an + * approximation for it) is usually desired. Finding a true minimal vertex cover + * is an NP-Complete problem. For more on the vertex cover problem, see + * http://mathworld.wolfram.com/VertexCover.html + * + * @author Linda Buisman + * @since Nov 6, 2003 + */ +public abstract class VertexCovers +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Finds a 2-approximation for a minimal vertex cover of the specified + * graph. The algorithm promises a cover that is at most double the size of + * a minimal cover. The algorithm takes O(|E|) time. + * + *

For more details see Jenny Walter, CMPU-240: Lecture notes for + * Language Theory and Computation, Fall 2002, Vassar College, + * http://www.cs.vassar.edu/~walter/cs241index/lectures/PDF/approx.pdf. + *

+ * + * @param g the graph for which vertex cover approximation is to be found. + * + * @return a set of vertices which is a vertex cover for the specified + * graph. + */ + public static Set find2ApproximationCover(Graph g) + { + // C <-- {} + Set cover = new HashSet(); + + // G'=(V',E') <-- G(V,E) + Subgraph> sg = + new Subgraph>( + g, + null, + null); + + // while E' is non-empty + while (sg.edgeSet().size() > 0) { + // let (u,v) be an arbitrary edge of E' + E e = sg.edgeSet().iterator().next(); + + // C <-- C U {u,v} + V u = g.getEdgeSource(e); + V v = g.getEdgeTarget(e); + cover.add(u); + cover.add(v); + + // remove from E' every edge incident on either u or v + sg.removeVertex(u); + sg.removeVertex(v); + } + + return cover; // return C + } + + /** + * Finds a greedy approximation for a minimal vertex cover of a specified + * graph. At each iteration, the algorithm picks the vertex with the highest + * degree and adds it to the cover, until all edges are covered. + * + *

The algorithm works on undirected graphs, but can also work on + * directed graphs when their edge-directions are ignored. To ignore edge + * directions you can use {@link org.jgrapht.Graphs#undirectedGraph(Graph)} + * or {@link org.jgrapht.graph.AsUndirectedGraph}.

+ * + * @param g the graph for which vertex cover approximation is to be found. + * + * @return a set of vertices which is a vertex cover for the specified + * graph. + */ + public static Set findGreedyCover(UndirectedGraph g) + { + // C <-- {} + Set cover = new HashSet(); + + // G' <-- G + UndirectedGraph sg = new UndirectedSubgraph(g, null, null); + + // compare vertices in descending order of degree + VertexDegreeComparator comp = + new VertexDegreeComparator(sg); + + // while G' != {} + while (sg.edgeSet().size() > 0) { + // v <-- vertex with maximum degree in G' + V v = Collections.max(sg.vertexSet(), comp); + + // C <-- C U {v} + cover.add(v); + + // remove from G' every edge incident on v, and v itself + sg.removeVertex(v); + } + + return cover; + } +} + +// End VertexCovers.java diff --git a/wdl/org/jgrapht/alg/package.html b/wdl/org/jgrapht/alg/package.html new file mode 100644 index 0000000..041cd4e --- /dev/null +++ b/wdl/org/jgrapht/alg/package.html @@ -0,0 +1,6 @@ + + + +Algorithms provided with JGraphT. + + \ No newline at end of file diff --git a/wdl/org/jgrapht/alg/util/UnionFind.java b/wdl/org/jgrapht/alg/util/UnionFind.java new file mode 100644 index 0000000..dcdb8aa --- /dev/null +++ b/wdl/org/jgrapht/alg/util/UnionFind.java @@ -0,0 +1,168 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2010, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * UnionFind.java + * ------------------------- + * (C) Copyright 2010-2010, by Tom Conerly and Contributors. + * + * Original Author: Tom Conerly + * Contributor(s): + * + * Changes + * ------- + * 02-Feb-2010 : Initial revision (TC); + * + */ +package org.jgrapht.alg.util; + +import java.util.*; + + +/** + * An implementation of Union + * Find data structure. Union Find is a disjoint-set data structure. It + * supports two operations: finding the set a specific element is in, and + * merging two sets. The implementation uses union by rank and path compression + * to achieve an amortized cost of O(a(n)) per operation where a is the inverse + * Ackermann function. UnionFind uses the hashCode and equals method of the + * elements it operates on. + * + * @author Tom Conerly + * @since Feb 10, 2010 + */ +public class UnionFind +{ + //~ Instance fields -------------------------------------------------------- + + private Map parentMap; + private Map rankMap; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a UnionFind instance with all of the elements of elements in + * seperate sets. + */ + public UnionFind(Set elements) + { + parentMap = new HashMap(); + rankMap = new HashMap(); + for (T element : elements) { + parentMap.put(element, element); + rankMap.put(element, 0); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Adds a new element to the data structure in its own set. + * + * @param element The element to add. + */ + public void addElement(T element) + { + parentMap.put(element, element); + rankMap.put(element, 0); + } + + /** + * @return map from element to parent element + */ + protected Map getParentMap() + { + return parentMap; + } + + /** + * @return map from element to rank + */ + protected Map getRankMap() + { + return rankMap; + } + + /** + * Returns the representative element of the set that element is in. + * + * @param element The element to find. + * + * @return The element representing the set the element is in. + */ + public T find(T element) + { + if (!parentMap.containsKey(element)) { + throw new IllegalArgumentException( + "elements must be contained in given set"); + } + + T parent = parentMap.get(element); + if (parent.equals(element)) { + return element; + } + + T newParent = find(parent); + parentMap.put(element, newParent); + return newParent; + } + + /** + * Merges the sets which contain element1 and element2. + * + * @param element1 The first element to union. + * @param element2 The second element to union. + */ + public void union(T element1, T element2) + { + if (!parentMap.containsKey(element1) + || !parentMap.containsKey(element2)) + { + throw new IllegalArgumentException( + "elements must be contained in given set"); + } + + T parent1 = find(element1); + T parent2 = find(element2); + + //check if the elements are already in the same set + if (parent1.equals(parent2)) { + return; + } + + int rank1 = rankMap.get(parent1); + int rank2 = rankMap.get(parent2); + if (rank1 > rank2) { + parentMap.put(parent2, parent1); + } else if (rank1 < rank2) { + parentMap.put(parent1, parent2); + } else { + parentMap.put(parent2, parent1); + rankMap.put(parent1, rank1 + 1); + } + } +} + +// End UnionFind.java diff --git a/wdl/org/jgrapht/alg/util/VertexDegreeComparator.java b/wdl/org/jgrapht/alg/util/VertexDegreeComparator.java new file mode 100644 index 0000000..a09d615 --- /dev/null +++ b/wdl/org/jgrapht/alg/util/VertexDegreeComparator.java @@ -0,0 +1,134 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------------- + * VertexDegreeComparator.java + * --------------------------- + * (C) Copyright 2003-2008, by Linda Buisman and Contributors. + * + * Original Author: Linda Buisman + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 06-Nov-2003 : Initial revision (LB); + * 07-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.alg.util; + +import org.jgrapht.*; + + +/** + * Compares two vertices based on their degree. + * + *

Used by greedy algorithms that need to sort vertices by their degree. Two + * vertices are considered equal if their degrees are equal.

+ * + * @author Linda Buisman + * @since Nov 6, 2003 + */ +public class VertexDegreeComparator + implements java.util.Comparator +{ + //~ Instance fields -------------------------------------------------------- + + /** + * The graph that contains the vertices to be compared. + */ + private UndirectedGraph graph; + + /** + * The sort order for vertex degree. true for ascending degree + * order (smaller degrees first), false for descending. + */ + private boolean ascendingOrder; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a comparator for comparing the degrees of vertices in the + * specified graph. The comparator compares in ascending order of degrees + * (lowest first). + * + * @param g graph with respect to which the degree is calculated. + */ + public VertexDegreeComparator(UndirectedGraph g) + { + this(g, true); + } + + /** + * Creates a comparator for comparing the degrees of vertices in the + * specified graph. + * + * @param g graph with respect to which the degree is calculated. + * @param ascendingOrder true - compares in ascending order of degrees + * (lowest first), false - compares in descending order of degrees (highest + * first). + */ + public VertexDegreeComparator( + UndirectedGraph g, + boolean ascendingOrder) + { + graph = g; + this.ascendingOrder = ascendingOrder; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Compare the degrees of v1 and v2, taking into + * account whether ascending or descending order is used. + * + * @param v1 the first vertex to be compared. + * @param v2 the second vertex to be compared. + * + * @return -1 if v1 comes before v2, +1 if + * v1 comes after v2, 0 if equal. + */ + public int compare(V v1, V v2) + { + int degree1 = graph.degreeOf(v1); + int degree2 = graph.degreeOf(v2); + + if (((degree1 < degree2) && ascendingOrder) + || ((degree1 > degree2) && !ascendingOrder)) + { + return -1; + } else if ( + ((degree1 > degree2) && ascendingOrder) + || ((degree1 < degree2) && !ascendingOrder)) + { + return 1; + } else { + return 0; + } + } +} + +// End VertexDegreeComparator.java diff --git a/wdl/org/jgrapht/alg/util/package.html b/wdl/org/jgrapht/alg/util/package.html new file mode 100644 index 0000000..38c56f6 --- /dev/null +++ b/wdl/org/jgrapht/alg/util/package.html @@ -0,0 +1,6 @@ + + + +Utilities used by JGraphT algorithms. + + diff --git a/wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java b/wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java new file mode 100644 index 0000000..134be60 --- /dev/null +++ b/wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java @@ -0,0 +1,103 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------------- + * ConnectedComponentTraversalEvent.java + * ------------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): - + * + * $Id: ConnectedComponentTraversalEvent.java 487 2006-07-02 00:53:17Z + * perfecthash $ + * + * Changes + * ------- + * 11-Aug-2003 : Initial revision (BN); + * + */ +package org.jgrapht.event; + +import java.util.*; + + +/** + * A traversal event with respect to a connected component. + * + * @author Barak Naveh + * @since Aug 11, 2003 + */ +public class ConnectedComponentTraversalEvent + extends EventObject +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3834311717709822262L; + + /** + * Connected component traversal started event. + */ + public static final int CONNECTED_COMPONENT_STARTED = 31; + + /** + * Connected component traversal finished event. + */ + public static final int CONNECTED_COMPONENT_FINISHED = 32; + + //~ Instance fields -------------------------------------------------------- + + /** + * The type of this event. + */ + private int type; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new ConnectedComponentTraversalEvent. + * + * @param eventSource the source of the event. + * @param type the type of event. + */ + public ConnectedComponentTraversalEvent(Object eventSource, int type) + { + super(eventSource); + this.type = type; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the event type. + * + * @return the event type. + */ + public int getType() + { + return type; + } +} + +// End ConnectedComponentTraversalEvent.java diff --git a/wdl/org/jgrapht/event/EdgeTraversalEvent.java b/wdl/org/jgrapht/event/EdgeTraversalEvent.java new file mode 100644 index 0000000..4cd33ed --- /dev/null +++ b/wdl/org/jgrapht/event/EdgeTraversalEvent.java @@ -0,0 +1,93 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------- + * EdgeTraversalEvent.java + * ----------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 11-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +import java.util.*; + + +/** + * A traversal event for a graph edge. + * + * @author Barak Naveh + * @since Aug 11, 2003 + */ +public class EdgeTraversalEvent + extends EventObject +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 4050768173789820979L; + + //~ Instance fields -------------------------------------------------------- + + /** + * The traversed edge. + */ + protected E edge; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new EdgeTraversalEvent. + * + * @param eventSource the source of the event. + * @param edge the traversed edge. + */ + public EdgeTraversalEvent(Object eventSource, E edge) + { + super(eventSource); + this.edge = edge; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the traversed edge. + * + * @return the traversed edge. + */ + public E getEdge() + { + return edge; + } +} + +// End EdgeTraversalEvent.java diff --git a/wdl/org/jgrapht/event/GraphChangeEvent.java b/wdl/org/jgrapht/event/GraphChangeEvent.java new file mode 100644 index 0000000..7b0a6a9 --- /dev/null +++ b/wdl/org/jgrapht/event/GraphChangeEvent.java @@ -0,0 +1,93 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------- + * GraphChangeEvent.java + * --------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 10-Aug-2003 : Initial revision (BN); + * + */ +package org.jgrapht.event; + +import java.util.*; + + +/** + * An event which indicates that a graph has changed. This class is a root for + * graph change events. + * + * @author Barak Naveh + * @since Aug 10, 2003 + */ +public class GraphChangeEvent + extends EventObject +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3834592106026382391L; + + //~ Instance fields -------------------------------------------------------- + + /** + * The type of graph change this event indicates. + */ + protected int type; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new graph change event. + * + * @param eventSource the source of the event. + * @param type the type of event. + */ + public GraphChangeEvent(Object eventSource, int type) + { + super(eventSource); + this.type = type; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the event type. + * + * @return the event type. + */ + public int getType() + { + return type; + } +} + +// End GraphChangeEvent.java diff --git a/wdl/org/jgrapht/event/GraphEdgeChangeEvent.java b/wdl/org/jgrapht/event/GraphEdgeChangeEvent.java new file mode 100644 index 0000000..bfe47c0 --- /dev/null +++ b/wdl/org/jgrapht/event/GraphEdgeChangeEvent.java @@ -0,0 +1,169 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * GraphEdgeChangeEvent.java + * ------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 10-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +/** + * An event which indicates that a graph edge has changed, or is about to + * change. The event can be used either as an indication after the edge + * has been added or removed, or before it is added. The type of the + * event can be tested using the {@link + * org.jgrapht.event.GraphChangeEvent#getType()} method. + * + * @author Barak Naveh + * @since Aug 10, 2003 + */ +public class GraphEdgeChangeEvent + extends GraphChangeEvent +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3618134563335844662L; + + /** + * Before edge added event. This event is fired before an edge is added to a + * graph. + */ + public static final int BEFORE_EDGE_ADDED = 21; + + /** + * Before edge removed event. This event is fired before an edge is removed + * from a graph. + */ + public static final int BEFORE_EDGE_REMOVED = 22; + + /** + * Edge added event. This event is fired after an edge is added to a graph. + */ + public static final int EDGE_ADDED = 23; + + /** + * Edge removed event. This event is fired after an edge is removed from a + * graph. + */ + public static final int EDGE_REMOVED = 24; + + //~ Instance fields -------------------------------------------------------- + + /** + * The edge that this event is related to. + */ + protected E edge; + + /** + * The source vertex of the edge that this event is related to. + */ + protected V edgeSource; + + /** + * The target vertex of the edge that this event is related to. + */ + protected V edgeTarget; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for GraphEdgeChangeEvent. + * + * @param eventSource the source of this event. + * @param type the event type of this event. + * @param edge the edge that this event is related to. + * + * @deprecated Use new constructor which takes vertex parameters. + */ + public GraphEdgeChangeEvent( + Object eventSource, int type, E edge) + { + this(eventSource, type, edge, null, null); + } + + /** + * Constructor for GraphEdgeChangeEvent. + * + * @param eventSource the source of this event. + * @param type the event type of this event. + * @param edge the edge that this event is related to. + * @param edgeSource edge source vertex + * @param edgeTarget edge target vertex + */ + public GraphEdgeChangeEvent( + Object eventSource, int type, E edge, + V edgeSource, V edgeTarget) + { + super(eventSource, type); + this.edge = edge; + this.edgeSource = edgeSource; + this.edgeTarget = edgeTarget; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the edge that this event is related to. + * + * @return event edge + */ + public E getEdge() + { + return edge; + } + + /** + * Returns the source vertex that this event is related to. + * + * @return event source vertex + */ + public V getEdgeSource() + { + return edgeSource; + } + + /** + * Returns the target vertex that this event is related to. + * + * @return event target vertex + */ + public V getEdgeTarget() + { + return edgeTarget; + } +} + +// End GraphEdgeChangeEvent.java diff --git a/wdl/org/jgrapht/event/GraphListener.java b/wdl/org/jgrapht/event/GraphListener.java new file mode 100644 index 0000000..fb185c0 --- /dev/null +++ b/wdl/org/jgrapht/event/GraphListener.java @@ -0,0 +1,74 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * GraphListener.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +/** + * A listener that is notified when the graph changes. + * + *

If only notifications on vertex set changes are required it is more + * efficient to use the VertexSetListener.

+ * + * @author Barak Naveh + * @see VertexSetListener + * @since Jul 18, 2003 + */ +public interface GraphListener + extends VertexSetListener +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Notifies that an edge has been added to the graph. + * + * @param e the edge event. + */ + public void edgeAdded(GraphEdgeChangeEvent e); + + /** + * Notifies that an edge has been removed from the graph. + * + * @param e the edge event. + */ + public void edgeRemoved(GraphEdgeChangeEvent e); +} + +// End GraphListener.java diff --git a/wdl/org/jgrapht/event/GraphVertexChangeEvent.java b/wdl/org/jgrapht/event/GraphVertexChangeEvent.java new file mode 100644 index 0000000..7c7dd11 --- /dev/null +++ b/wdl/org/jgrapht/event/GraphVertexChangeEvent.java @@ -0,0 +1,119 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------------- + * GraphVertexChangeEvent.java + * --------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 10-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +/** + * An event which indicates that a graph vertex has changed, or is about to + * change. The event can be used either as an indication after the vertex + * has been added or removed, or before it is added. The type of the + * event can be tested using the {@link + * org.jgrapht.event.GraphChangeEvent#getType()} method. + * + * @author Barak Naveh + * @since Aug 10, 2003 + */ +public class GraphVertexChangeEvent + extends GraphChangeEvent +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3690189962679104053L; + + /** + * Before vertex added event. This event is fired before a vertex is added + * to a graph. + */ + public static final int BEFORE_VERTEX_ADDED = 11; + + /** + * Before vertex removed event. This event is fired before a vertex is + * removed from a graph. + */ + public static final int BEFORE_VERTEX_REMOVED = 12; + + /** + * Vertex added event. This event is fired after a vertex is added to a + * graph. + */ + public static final int VERTEX_ADDED = 13; + + /** + * Vertex removed event. This event is fired after a vertex is removed from + * a graph. + */ + public static final int VERTEX_REMOVED = 14; + + //~ Instance fields -------------------------------------------------------- + + /** + * The vertex that this event is related to. + */ + protected V vertex; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new GraphVertexChangeEvent object. + * + * @param eventSource the source of the event. + * @param type the type of the event. + * @param vertex the vertex that the event is related to. + */ + public GraphVertexChangeEvent(Object eventSource, int type, V vertex) + { + super(eventSource, type); + this.vertex = vertex; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the vertex that this event is related to. + * + * @return the vertex that this event is related to. + */ + public V getVertex() + { + return vertex; + } +} + +// End GraphVertexChangeEvent.java diff --git a/wdl/org/jgrapht/event/TraversalListener.java b/wdl/org/jgrapht/event/TraversalListener.java new file mode 100644 index 0000000..605848e --- /dev/null +++ b/wdl/org/jgrapht/event/TraversalListener.java @@ -0,0 +1,100 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * TraversalListener.java + * ---------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Aug-2003 : Adaptation to new event model (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +/** + * A listener on graph iterator or on a graph traverser. + * + * @author Barak Naveh + * @since Jul 19, 2003 + */ +public interface TraversalListener +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Called to inform listeners that the traversal of the current connected + * component has finished. + * + * @param e the traversal event. + */ + public void connectedComponentFinished( + ConnectedComponentTraversalEvent e); + + /** + * Called to inform listeners that a traversal of a new connected component + * has started. + * + * @param e the traversal event. + */ + public void connectedComponentStarted(ConnectedComponentTraversalEvent e); + + /** + * Called to inform the listener that the specified edge have been visited + * during the graph traversal. Depending on the traversal algorithm, edge + * might be visited more than once. + * + * @param e the edge traversal event. + */ + public void edgeTraversed(EdgeTraversalEvent e); + + /** + * Called to inform the listener that the specified vertex have been visited + * during the graph traversal. Depending on the traversal algorithm, vertex + * might be visited more than once. + * + * @param e the vertex traversal event. + */ + public void vertexTraversed(VertexTraversalEvent e); + + /** + * Called to inform the listener that the specified vertex have been + * finished during the graph traversal. Exact meaning of "finish" is + * algorithm-dependent; e.g. for DFS, it means that all vertices reachable + * via the vertex have been visited as well. + * + * @param e the vertex traversal event. + */ + public void vertexFinished(VertexTraversalEvent e); +} + +// End TraversalListener.java diff --git a/wdl/org/jgrapht/event/TraversalListenerAdapter.java b/wdl/org/jgrapht/event/TraversalListenerAdapter.java new file mode 100644 index 0000000..a4985e0 --- /dev/null +++ b/wdl/org/jgrapht/event/TraversalListenerAdapter.java @@ -0,0 +1,93 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------------- + * TraversalListenerAdapter.java + * ----------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 06-Aug-2003 : Initial revision (BN); + * 11-Aug-2003 : Adaptation to new event model (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +/** + * An empty do-nothing implementation of the {@link TraversalListener} interface + * used for subclasses. + * + * @author Barak Naveh + * @since Aug 6, 2003 + */ +public class TraversalListenerAdapter + implements TraversalListener +{ + //~ Methods ---------------------------------------------------------------- + + /** + * @see TraversalListener#connectedComponentFinished(ConnectedComponentTraversalEvent) + */ + public void connectedComponentFinished( + ConnectedComponentTraversalEvent e) + { + } + + /** + * @see TraversalListener#connectedComponentStarted(ConnectedComponentTraversalEvent) + */ + public void connectedComponentStarted(ConnectedComponentTraversalEvent e) + { + } + + /** + * @see TraversalListener#edgeTraversed(EdgeTraversalEvent) + */ + public void edgeTraversed(EdgeTraversalEvent e) + { + } + + /** + * @see TraversalListener#vertexTraversed(VertexTraversalEvent) + */ + public void vertexTraversed(VertexTraversalEvent e) + { + } + + /** + * @see TraversalListener#vertexFinished(VertexTraversalEvent) + */ + public void vertexFinished(VertexTraversalEvent e) + { + } +} + +// End TraversalListenerAdapter.java diff --git a/wdl/org/jgrapht/event/VertexSetListener.java b/wdl/org/jgrapht/event/VertexSetListener.java new file mode 100644 index 0000000..c0dd692 --- /dev/null +++ b/wdl/org/jgrapht/event/VertexSetListener.java @@ -0,0 +1,77 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * VertexSetListener.java + * ---------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +import java.util.*; + + +/** + * A listener that is notified when the graph's vertex set changes. It should be + * used when only notifications on vertex-set changes are of interest. If + * all graph notifications are of interest better use + * GraphListener. + * + * @author Barak Naveh + * @see GraphListener + * @since Jul 18, 2003 + */ +public interface VertexSetListener + extends EventListener +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Notifies that a vertex has been added to the graph. + * + * @param e the vertex event. + */ + public void vertexAdded(GraphVertexChangeEvent e); + + /** + * Notifies that a vertex has been removed from the graph. + * + * @param e the vertex event. + */ + public void vertexRemoved(GraphVertexChangeEvent e); +} + +// End VertexSetListener.java diff --git a/wdl/org/jgrapht/event/VertexTraversalEvent.java b/wdl/org/jgrapht/event/VertexTraversalEvent.java new file mode 100644 index 0000000..c72e927 --- /dev/null +++ b/wdl/org/jgrapht/event/VertexTraversalEvent.java @@ -0,0 +1,93 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * VertexTraversalEvent.java + * ------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 11-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.event; + +import java.util.*; + + +/** + * A traversal event for a graph vertex. + * + * @author Barak Naveh + * @since Aug 11, 2003 + */ +public class VertexTraversalEvent + extends EventObject +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3688790267213918768L; + + //~ Instance fields -------------------------------------------------------- + + /** + * The traversed vertex. + */ + protected V vertex; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new VertexTraversalEvent. + * + * @param eventSource the source of the event. + * @param vertex the traversed vertex. + */ + public VertexTraversalEvent(Object eventSource, V vertex) + { + super(eventSource); + this.vertex = vertex; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns the traversed vertex. + * + * @return the traversed vertex. + */ + public V getVertex() + { + return vertex; + } +} + +// End VertexTraversalEvent.java diff --git a/wdl/org/jgrapht/event/package.html b/wdl/org/jgrapht/event/package.html new file mode 100644 index 0000000..9a0bf09 --- /dev/null +++ b/wdl/org/jgrapht/event/package.html @@ -0,0 +1,7 @@ + + + +Event classes and listener interfaces, used to provide a change +notification mechanism on graph modification events. + + diff --git a/wdl/org/jgrapht/experimental/GraphReader.java b/wdl/org/jgrapht/experimental/GraphReader.java new file mode 100644 index 0000000..0bee22e --- /dev/null +++ b/wdl/org/jgrapht/experimental/GraphReader.java @@ -0,0 +1,181 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * GraphReader.java + * ------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (BN); + * + */ +package org.jgrapht.experimental; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.generate.*; + + +public class GraphReader + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + // ~ Static fields/initializers -------------------------------------------- + + // ~ Instance fields ------------------------------------------------------- + + // ~ Static fields/initializers -------------------------------------------- + + // ~ Instance fields ------------------------------------------------------- + + private final BufferedReader _in; + private final boolean _isWeighted; + private final double _defaultWeight; + + // ~ Constructors ---------------------------------------------------------- + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new GraphReader. + */ + private GraphReader(Reader input, boolean isWeighted, double defaultWeight) + throws IOException + { + if (input instanceof BufferedReader) { + _in = (BufferedReader) input; + } else { + _in = new BufferedReader(input); + } + _isWeighted = isWeighted; + _defaultWeight = defaultWeight; + } + + /** + * Construct a new GraphReader. + */ + public GraphReader(Reader input) + throws IOException + { + this(input, false, 1); + } + + /** + * Construct a new GraphReader. + */ + public GraphReader(Reader input, double defaultWeight) + throws IOException + { + this(input, true, defaultWeight); + } + + //~ Methods ---------------------------------------------------------------- + + // ~ Methods --------------------------------------------------------------- + + private String [] split(final String src) + { + if (src == null) { + return null; + } + return src.split("\\s+"); + } + + private String [] skipComments() + { + String [] cols = null; + try { + cols = split(_in.readLine()); + while ( + (cols != null) + && ((cols.length == 0) + || cols[0].equals("c") + || cols[0].startsWith("%"))) + { + cols = split(_in.readLine()); + } + } catch (IOException e) { + } + return cols; + } + + private int readNodeCount() + { + final String [] cols = skipComments(); + if (cols[0].equals("p")) { + return Integer.parseInt(cols[1]); + } + return -1; + } + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + final int size = readNodeCount(); + if (resultMap == null) { + resultMap = new HashMap(); + } + + for (int i = 0; i < size; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + resultMap.put(Integer.toString(i + 1), newVertex); + } + String [] cols = skipComments(); + while (cols != null) { + if (cols[0].equals("e")) { + E edge = + target.addEdge( + resultMap.get(cols[1]), + resultMap.get(cols[2])); + if (_isWeighted && (edge != null)) { + double weight = _defaultWeight; + if (cols.length > 3) { + weight = Double.parseDouble(cols[3]); + } + ((WeightedGraph) target).setEdgeWeight(edge, weight); + } + } + cols = skipComments(); + } + } +} + +// End GraphReader.java diff --git a/wdl/org/jgrapht/experimental/GraphSquare.java b/wdl/org/jgrapht/experimental/GraphSquare.java new file mode 100644 index 0000000..4d10c73 --- /dev/null +++ b/wdl/org/jgrapht/experimental/GraphSquare.java @@ -0,0 +1,219 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * GraphSquare.java + * ---------------------- + * (C) Copyright 2004-2008, by Michael Behrisch and Contributors. + * + * Original Author: Michael Behrisch + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 14-Sep-2004 : Initial revision (MB); + * + */ +package org.jgrapht.experimental; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; +import org.jgrapht.graph.*; + + +/** + * DOCUMENT ME! + * + * @author Michael Behrisch + * @since Sep 14, 2004 + */ +public class GraphSquare + extends AbstractBaseGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -2642034600395594304L; + private static final String UNMODIFIABLE = "this graph is unmodifiable"; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for GraphSquare. + * + * @param g the graph of which a square is to be created. + * @param createLoops + */ + public GraphSquare(final Graph g, final boolean createLoops) + { + super(g.getEdgeFactory(), false, createLoops); + Graphs.addAllVertices(this, g.vertexSet()); + addSquareEdges(g, createLoops); + + if (g instanceof ListenableGraph) { + ((ListenableGraph) g).addGraphListener( + new GraphListener() { + public void edgeAdded(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + addEdgesStartingAt( + g, + g.getEdgeSource(edge), + g.getEdgeTarget(edge), + createLoops); + addEdgesStartingAt( + g, + g.getEdgeTarget(edge), + g.getEdgeSource(edge), + createLoops); + } + + public void edgeRemoved(GraphEdgeChangeEvent e) + { // this is not a very performant implementation + GraphSquare.super.removeAllEdges(edgeSet()); + addSquareEdges(g, createLoops); + } + + public void vertexAdded(GraphVertexChangeEvent e) + { + } + + public void vertexRemoved(GraphVertexChangeEvent e) + { + } + }); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#addEdge(Object, Object, E) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllEdges(Collection) + */ + public boolean removeAllEdges(Collection edges) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllEdges(V, V) + */ + public Set removeAllEdges(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllVertices(Collection) + */ + public boolean removeAllVertices(Collection vertices) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(E) + */ + public boolean removeEdge(E e) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(V, V) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeVertex(V) + */ + public boolean removeVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + private void addEdgesStartingAt( + final Graph g, + final V v, + final V u, + boolean createLoops) + { + if (!g.containsEdge(v, u)) { + return; + } + + final List adjVertices = Graphs.neighborListOf(g, u); + + for (int i = 0; i < adjVertices.size(); i++) { + final V w = adjVertices.get(i); + + if (g.containsEdge(u, w) && ((v != w) || createLoops)) { + super.addEdge(v, w); + } + } + } + + private void addSquareEdges(Graph g, boolean createLoops) + { + for (V v : g.vertexSet()) { + List adjVertices = Graphs.neighborListOf(g, v); + + for (int i = 0; i < adjVertices.size(); i++) { + addEdgesStartingAt(g, v, adjVertices.get(i), createLoops); + } + } + } +} + +// End GraphSquare.java diff --git a/wdl/org/jgrapht/experimental/GraphTests.java b/wdl/org/jgrapht/experimental/GraphTests.java new file mode 100644 index 0000000..8c099e1 --- /dev/null +++ b/wdl/org/jgrapht/experimental/GraphTests.java @@ -0,0 +1,118 @@ +package org.jgrapht.experimental; + +import java.util.*; + +import org.jgrapht.*; + + +public final class GraphTests +{ + //~ Constructors ----------------------------------------------------------- + + private GraphTests() + { + } + + //~ Methods ---------------------------------------------------------------- + + public static boolean isEmpty(Graph g) + { + return g.edgeSet().isEmpty(); + } + + public static boolean isComplete(Graph g) + { + int n = g.vertexSet().size(); + return g.edgeSet().size() + == (n * (n - 1) / 2); + } + + public static boolean isConnected(Graph g) + { + int numVertices = g.vertexSet().size(); + int numEdges = g.edgeSet().size(); + + if (numEdges < (numVertices - 1)) { + return false; + } + if ((numVertices < 2) + || (numEdges > ((numVertices - 1) * (numVertices - 2) / 2))) + { + return true; + } + + Set known = new HashSet(); + LinkedList queue = new LinkedList(); + V v = g.vertexSet().iterator().next(); + + queue.add(v); // start with node 1 + known.add(v); + + while (!queue.isEmpty()) { + v = queue.removeFirst(); + for ( + Iterator it = Graphs.neighborListOf(g, v).iterator(); + it.hasNext();) + { + v = it.next(); + if (!known.contains(v)) { + known.add(v); + queue.add(v); + } + } + } + return known.size() == numVertices; + } + + public static boolean isTree(Graph g) + { + return isConnected(g) + && (g.edgeSet().size() == (g.vertexSet().size() - 1)); + } + + public static boolean isBipartite(Graph g) + { + if ((4 * g.edgeSet().size()) + > (g.vertexSet().size() * g.vertexSet().size())) + { + return false; + } + if (isEmpty(g)) { + return true; + } + + Set unknown = new HashSet(g.vertexSet()); + LinkedList queue = new LinkedList(); + V v = unknown.iterator().next(); + Set odd = new HashSet(); + + queue.add(v); + + while (!unknown.isEmpty()) { + if (queue.isEmpty()) { + queue.add(unknown.iterator().next()); + } + + v = queue.removeFirst(); + unknown.remove(v); + + for ( + Iterator it = Graphs.neighborListOf(g, v).iterator(); + it.hasNext();) + { + V n = it.next(); + if (unknown.contains(n)) { + queue.add(n); + if (!odd.contains(v)) { + odd.add(n); + } + } else if (!(odd.contains(v) ^ odd.contains(n))) { + return false; + } + } + } + return true; + } +} + +// End GraphTests.java diff --git a/wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java b/wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java new file mode 100644 index 0000000..0f9981b --- /dev/null +++ b/wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java @@ -0,0 +1,171 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * PartiteRandomGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. + * + * Original Author: Michael Behrisch + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 13-Sep-2004 : Initial revision (MB); + * + */ +// package org.jgrapht.generate; +package org.jgrapht.experimental; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.generate.*; + + +/** + * PartiteRandomGraphGenerator generates a partite uniform random + * graph of any size. A partite uniform random graph contains edges chosen + * independently uniformly at random from the set of possible edges between + * partition classes. + * + * @author Michael Behrisch + * @since Sep 13, 2004 + */ +public class PartiteRandomGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private final int [] numVertices; + private final int numEdges; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new PartiteRandomGraphGenerator for a bipartite graph. + * + * @param numVertices1 number of vertices in the first partition + * @param numVertices2 number of vertices in the second partition + * @param numEdges number of edges to be generated + * + * @throws IllegalArgumentException + */ + public PartiteRandomGraphGenerator( + int numVertices1, + int numVertices2, + int numEdges) + { + if ((numVertices1 < 0) || (numVertices2 < 0)) { + throw new IllegalArgumentException("must be non-negative"); + } + + if ((numEdges < 0) || (numEdges > (numVertices1 * numVertices2))) { + throw new IllegalArgumentException("illegal number of edges"); + } + + final int [] numVertices = { + numVertices1, + numVertices2 + }; + this.numVertices = numVertices; + this.numEdges = numEdges; + } + + /** + * Construct a new PartiteRandomGraphGenerator for a k-partite graph. + * + * @param numVertices number of vertices in the k partitions + * @param numEdges number of edges to be generated between any two + * partitions + * + * @throws IllegalArgumentException + */ + public PartiteRandomGraphGenerator(int [] numVertices, int numEdges) + { + if (numEdges < 0) { + throw new IllegalArgumentException("illegal number of edges"); + } + + for (int i = 0; i < numVertices.length; i++) { + if (numVertices[i] < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + for (int j = 0; j < i; j++) { + if (numEdges > (numVertices[i] * numVertices[j])) { + throw new IllegalArgumentException( + "illegal number of edges"); + } + } + } + + this.numVertices = numVertices; + this.numEdges = numEdges; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * TODO hb 30-nov-05: document me + * + * @param target + * @param vertexFactory + * @param resultMap some array of vertices + * + * @see GraphGenerator#generateGraph + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + Object [][] vertices = new Object[numVertices.length][]; + + for (int i = 0; i < numVertices.length; i++) { + vertices[i] = + RandomGraphHelper.addVertices( + target, + vertexFactory, + numVertices[i]); + + if (resultMap != null) { + resultMap.put(Integer.toString(i), vertices[i]); + } + + for (int j = 0; j < i; j++) { + RandomGraphHelper.addEdges( + target, + Arrays.asList(vertices[i]), + Arrays.asList(vertices[j]), + numEdges); + } + } + } +} + +// End PartiteRandomGraphGenerator.java diff --git a/wdl/org/jgrapht/experimental/RandomGraphHelper.java b/wdl/org/jgrapht/experimental/RandomGraphHelper.java new file mode 100644 index 0000000..731f9e5 --- /dev/null +++ b/wdl/org/jgrapht/experimental/RandomGraphHelper.java @@ -0,0 +1,126 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * RandomGraphHelper.java + * ------------------- + * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. + * + * Original Author: Michael Behrisch + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 13-Sep-2004 : Initial revision (MB); + * + */ +// package org.jgrapht.generate; +package org.jgrapht.experimental; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * UniformRandomGraphGenerator generates a uniform random graph + * of any size. A uniform random graph contains edges chosen independently + * uniformly at random from the set of all possible edges. + * + * @author Michael Behrisch + * @since Sep 13, 2004 + */ +public final class RandomGraphHelper +{ + //~ Static fields/initializers --------------------------------------------- + + private static final Random randSingleton = new Random(); + + //~ Constructors ----------------------------------------------------------- + + /** + * . + */ + private RandomGraphHelper() + { + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see GraphGenerator#generateGraph + */ + @SuppressWarnings("unchecked") + public static void addEdges( + Graph target, + List sourceVertices, + List destVertices, + int numEdges) + { + int sourceSize = sourceVertices.size(); + int destSize = destVertices.size(); + + for (int i = 0; i < numEdges; ++i) { + while ( + target.addEdge( + sourceVertices.get(randSingleton.nextInt( + sourceSize)), + destVertices.get(randSingleton.nextInt(destSize))) + == null) + { + ; + } + } + } + + /** + * . + * + * @param target + * @param vertexFactory + * @param numVertices + * + * @return + */ + @SuppressWarnings("unchecked") + public static Object [] addVertices( + Graph target, + VertexFactory vertexFactory, + int numVertices) + { + Object [] vertices = new Object[numVertices]; + + for (int i = 0; i < numVertices; ++i) { + vertices[i] = vertexFactory.createVertex(); + target.addVertex(vertices[i]); + } + + return vertices; + } +} + +// End RandomGraphHelper.java diff --git a/wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java b/wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java new file mode 100644 index 0000000..6b34839 --- /dev/null +++ b/wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java @@ -0,0 +1,115 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * UniformRandomGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. + * + * Original Author: Michael Behrisch + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 13-Sep-2004 : Initial revision (MB); + * + */ +// package org.jgrapht.generate; +package org.jgrapht.experimental; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.generate.*; + + +/** + * UniformRandomGraphGenerator generates a uniform random graph + * of any size. A uniform random graph contains edges chosen independently + * uniformly at random from the set of all possible edges. + * + * @author Michael Behrisch + * @since Sep 13, 2004 + */ +public class UniformRandomGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private final int numEdges; + private final int numVertices; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new UniformRandomGraphGenerator. + * + * @param numVertices number of vertices to be generated + * @param numEdges number of edges to be generated + * + * @throws IllegalArgumentException + */ + public UniformRandomGraphGenerator(int numVertices, int numEdges) + { + if (numVertices < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + if ((numEdges < 0) + || (numEdges > (numVertices * (numVertices - 1) / 2))) + { + throw new IllegalArgumentException("illegal number of edges"); + } + + this.numVertices = numVertices; + this.numEdges = numEdges; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see GraphGenerator#generateGraph + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + Object [] vertices = + RandomGraphHelper.addVertices( + target, + vertexFactory, + numVertices); + RandomGraphHelper.addEdges( + target, + Arrays.asList(vertices), + Arrays.asList(vertices), + numEdges); + } +} + +// End UniformRandomGraphGenerator.java diff --git a/wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java b/wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java new file mode 100644 index 0000000..d366996 --- /dev/null +++ b/wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java @@ -0,0 +1,17 @@ +package org.jgrapht.experimental.alg; + +import java.util.*; + + +public interface ApproximationAlgorithm +{ + //~ Methods ---------------------------------------------------------------- + + ResultType getUpperBound(Map optionalData); + + ResultType getLowerBound(Map optionalData); + + boolean isExact(); +} + +// End ApproximationAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java b/wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java new file mode 100644 index 0000000..a3a4a2e --- /dev/null +++ b/wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java @@ -0,0 +1,13 @@ +package org.jgrapht.experimental.alg; + +import java.util.*; + + +public interface ExactAlgorithm +{ + //~ Methods ---------------------------------------------------------------- + + ResultType getResult(Map optionalData); +} + +// End ExactAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java b/wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java new file mode 100644 index 0000000..fdcbc5c --- /dev/null +++ b/wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java @@ -0,0 +1,49 @@ +/** + * + */ +package org.jgrapht.experimental.alg; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * @author micha + */ +public abstract class IntArrayGraphAlgorithm +{ + //~ Instance fields -------------------------------------------------------- + + protected final List _vertices; + protected final int [][] _neighbors; + protected final Map _vertexToPos; + + //~ Constructors ----------------------------------------------------------- + + /** + * @param g + */ + public IntArrayGraphAlgorithm(final Graph g) + { + final int numVertices = g.vertexSet().size(); + _vertices = new ArrayList(numVertices); + _neighbors = new int[numVertices][]; + _vertexToPos = new HashMap(numVertices); + for (V vertex : g.vertexSet()) { + _neighbors[_vertices.size()] = new int[g.edgesOf(vertex).size()]; + _vertexToPos.put(vertex, _vertices.size()); + _vertices.add(vertex); + } + for (int i = 0; i < numVertices; i++) { + int nbIndex = 0; + final V vertex = _vertices.get(i); + for (E e : g.edgesOf(vertex)) { + _neighbors[i][nbIndex++] = + _vertexToPos.get(Graphs.getOppositeVertex(g, e, vertex)); + } + } + } +} + +// End IntArrayGraphAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java b/wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java new file mode 100644 index 0000000..dfa66f9 --- /dev/null +++ b/wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java @@ -0,0 +1,99 @@ +/** + * + */ +package org.jgrapht.experimental.alg.color; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.experimental.alg.*; + + +/** + * @author micha + */ +public class BrownBacktrackColoring + extends IntArrayGraphAlgorithm + implements ExactAlgorithm +{ + //~ Instance fields -------------------------------------------------------- + + private int [] _color; + private int [] _colorCount; + private BitSet [] _allowedColors; + private int _chi; + + //~ Constructors ----------------------------------------------------------- + + /** + * @param g + */ + public BrownBacktrackColoring(final Graph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + void recursiveColor(int pos) + { + _colorCount[pos] = _colorCount[pos - 1]; + _allowedColors[pos].set(0, _colorCount[pos] + 1); + for (int i = 0; i < _neighbors[pos].length; i++) { + final int nb = _neighbors[pos][i]; + if (_color[nb] > 0) { + _allowedColors[pos].clear(_color[nb]); + } + } + for ( + int i = 1; + (i <= _colorCount[pos]) + && (_colorCount[pos] < _chi); + i++) + { + if (_allowedColors[pos].get(i)) { + _color[pos] = i; + if (pos < (_neighbors.length - 1)) { + recursiveColor(pos + 1); + } else { + _chi = _colorCount[pos]; + } + } + } + if ((_colorCount[pos] + 1) < _chi) { + _colorCount[pos]++; + _color[pos] = _colorCount[pos]; + if (pos < (_neighbors.length - 1)) { + recursiveColor(pos + 1); + } else { + _chi = _colorCount[pos]; + } + } + _color[pos] = 0; + } + + /* (non-Javadoc) + * @see org.jgrapht.experimental.alg.ExactAlgorithm#getResult() + */ + public Integer getResult(Map additionalData) + { + _chi = _neighbors.length; + _color = new int[_neighbors.length]; + _color[0] = 1; + _colorCount = new int[_neighbors.length]; + _colorCount[0] = 1; + _allowedColors = new BitSet[_neighbors.length]; + for (int i = 0; i < _neighbors.length; i++) { + _allowedColors[i] = new BitSet(1); + } + recursiveColor(1); + if (additionalData != null) { + for (int i = 0; i < _vertices.size(); i++) { + additionalData.put(_vertices.get(i), _color[i]); + } + } + return _chi; + } +} + +// End BrownBacktrackColoring.java diff --git a/wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java b/wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java new file mode 100644 index 0000000..d9a586b --- /dev/null +++ b/wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java @@ -0,0 +1,185 @@ +package org.jgrapht.experimental.alg.color; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.experimental.alg.*; + + +public class GreedyColoring + extends IntArrayGraphAlgorithm + implements ApproximationAlgorithm +{ + //~ Static fields/initializers --------------------------------------------- + + public static final int BEST_ORDER = 0; + public static final int NATURAL_ORDER = 1; + public static final int SMALLEST_DEGREE_LAST_ORDER = 2; + public static final int LARGEST_SATURATION_FIRST_ORDER = 3; + + //~ Instance fields -------------------------------------------------------- + + private int _order = BEST_ORDER; + + //~ Constructors ----------------------------------------------------------- + + /** + * @param g + */ + public GreedyColoring(final Graph g) + { + this(g, BEST_ORDER); + } + + /** + * @param g + */ + public GreedyColoring(final Graph g, final int method) + { + super(g); + _order = method; + } + + //~ Methods ---------------------------------------------------------------- + + int color(int [] order) + { + final int [] color = new int[_neighbors.length]; + int maxColor = 1; + BitSet usedColors = new BitSet(_neighbors.length); + + for (int i = 0; i < _neighbors.length; i++) { + final int v = (order == null) ? i : order[i]; + usedColors.clear(); + for (int j = 0; j < _neighbors[v].length; j++) { + final int nb = _neighbors[v][j]; + if (color[nb] > 0) { + usedColors.set(color[nb]); + } + } + color[v] = usedColors.nextClearBit(1); + if (color[v] > maxColor) { + maxColor = color[v]; + } + } + return maxColor; + } + + int [] smallestDegreeLastOrder() + { + final int [] order = new int[_neighbors.length]; + final int [] degree = new int[_neighbors.length]; + final List> buckets = + new ArrayList>(_neighbors.length); + int index = _neighbors.length - 1; + + for (int i = 0; i < _neighbors.length; i++) { + buckets.add(new ArrayList()); + degree[i] = _neighbors[i].length; + } + for (int i = 0; i < _neighbors.length; i++) { + buckets.get(degree[i]).add(i); + } + for (int i = 0; i < _neighbors.length; i++) { + while (buckets.get(i).size() > 0) { + final int s = buckets.get(i).size() - 1; + final int vertex = (Integer) buckets.get(i).get(s); + buckets.get(i).remove(s); + degree[vertex] = -1; + order[index--] = vertex; + for (int j = 0; j < _neighbors[vertex].length; j++) { + final int nb = _neighbors[vertex][j]; + if (degree[nb] >= 0) { + buckets.get(degree[nb]).remove(new Integer(nb)); + degree[nb]--; + buckets.get(degree[nb]).add(nb); + if (degree[nb] < i) { + i = degree[nb]; + } + } + } + } + } + return order; + } + + int [] largestSaturationFirstOrder() + { + final int [] satur = new int[_neighbors.length]; + final int [] buckets = new int[_neighbors.length]; + final int [] cumBucketSize = new int[_neighbors.length]; + final int [] bucketIndex = new int[_neighbors.length]; + int index = 0; + int maxSat = 0; + + for (int i = 0; i < _neighbors.length; i++) { + buckets[i] = i; + bucketIndex[i] = i; + } + cumBucketSize[0] = _neighbors.length; + while (index < _neighbors.length) { + while ( + (maxSat > 0) + && (cumBucketSize[maxSat] == cumBucketSize[maxSat - 1])) + { + cumBucketSize[maxSat--] = 0; + } + final int v = buckets[cumBucketSize[maxSat] - 1]; + cumBucketSize[maxSat]--; + satur[v] = -1; + index++; + for (int j = 0; j < _neighbors[v].length; j++) { + final int nb = (int) _neighbors[v][j]; + final int bi = bucketIndex[nb]; + if (satur[nb] >= 0) { + if (bi != (cumBucketSize[satur[nb]] - 1)) { + buckets[bi] = buckets[cumBucketSize[satur[nb]] - 1]; + buckets[cumBucketSize[satur[nb]] - 1] = nb; + bucketIndex[nb] = cumBucketSize[satur[nb]] - 1; + bucketIndex[buckets[bi]] = bi; + } + cumBucketSize[satur[nb]]--; + satur[nb]++; + if (cumBucketSize[satur[nb]] == 0) { + cumBucketSize[satur[nb]] = + cumBucketSize[satur[nb] - 1] + 1; + } + if (satur[nb] > maxSat) { + maxSat = satur[nb]; + } + } + } + } + Collections.reverse(Arrays.asList(buckets)); + return buckets; + } + + public Integer getLowerBound(Map optionalData) + { + return 0; + } + + public Integer getUpperBound(Map optionalData) + { + switch (_order) { + case BEST_ORDER: + return Math.min( + Math.min(color(null), color(smallestDegreeLastOrder())), + color(largestSaturationFirstOrder())); + case NATURAL_ORDER: + return color(null); + case SMALLEST_DEGREE_LAST_ORDER: + return color(smallestDegreeLastOrder()); + case LARGEST_SATURATION_FIRST_ORDER: + return color(largestSaturationFirstOrder()); + } + return _neighbors.length; + } + + public boolean isExact() + { + return false; + } +} + +// End GreedyColoring.java diff --git a/wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java b/wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java new file mode 100644 index 0000000..7a89dc6 --- /dev/null +++ b/wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java @@ -0,0 +1,1199 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * DirectedAcyclicGraph.java + * ------------------- + * (C) Copyright 2008-2008, by Peter Giles and Contributors. + * + * Original Author: Peter Giles + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 17-Mar-2008 : Initial revision (PG); + * 23-Aug-2008 : Added VisitedBitSetImpl and made it the default (JVS); + * + */ +package org.jgrapht.experimental.dag; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + *

DirectedAcyclicGraph implements a DAG that can be modified (vertices & + * edges added and removed), is guaranteed to remain acyclic, and provides fast + * topological order iteration.

+ * + *

This is done using a dynamic topological sort which is based on the + * algorithm PK described in "D. Pearce & P. Kelly, 2007: A Dynamic + * Topological Sort Algorithm for Directed Acyclic Graphs", (see Paper or ACM link for details). + *

+ * + *

The implementation differs from the algorithm specified in the above paper + * in some ways, perhaps most notably in that the topological ordering is stored + * by default using two HashMaps, which will have some effects on runtime, but + * also allows for vertex addition and removal, and other operations which are + * helpful for manipulating or combining DAGs. This storage mechanism is + * pluggable for subclassers.

+ * + *

This class makes no claims to thread safety, and concurrent usage from + * multiple threads will produce undefined results.

+ * + * @author Peter Giles, gilesp@u.washington.edu + */ +public class DirectedAcyclicGraph + extends SimpleDirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 4522128427004938150L; + + //~ Instance fields -------------------------------------------------------- + + private TopoComparator topoComparator; + + private TopoOrderMapping topoOrderMap; + + private int maxTopoIndex = 0; + private int minTopoIndex = 0; + + // this update count is used to keep internal topological iterators honest + private long topologyUpdateCount = 0; + + /** + * Pluggable VisitedFactory implementation + */ + private VisitedFactory visitedFactory = new VisitedBitSetImpl(); + + /** + * Pluggable TopoOrderMappingFactory implementation + */ + private TopoOrderMappingFactory topoOrderFactory = new TopoVertexBiMap(); + + //~ Constructors ----------------------------------------------------------- + + public DirectedAcyclicGraph(Class arg0) + { + super(arg0); + initialize(); + } + + DirectedAcyclicGraph( + Class arg0, + VisitedFactory visitedFactory, + TopoOrderMappingFactory topoOrderFactory) + { + super(arg0); + if (visitedFactory != null) { + this.visitedFactory = visitedFactory; + } + if (topoOrderFactory != null) { + this.topoOrderFactory = topoOrderFactory; + } + initialize(); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * set the topoOrderMap based on the current factory, and create the + * comparator; + */ + private void initialize() + { + topoOrderMap = topoOrderFactory.getTopoOrderMapping(); + topoComparator = new TopoComparator(topoOrderMap); + } + + /** + * iterator will traverse the vertices in topological order, meaning that + * for a directed graph G = (V,E), if there exists a path from vertex va to + * vertex vb then va is guaranteed to come before vertex vb in the iteration + * order. + * + * @return an iterator that will traverse the graph in topological order + */ + public Iterator iterator() + { + return new TopoIterator(); + } + + /** + * adds the vertex if it wasn't already in the graph, and puts it at the top + * of the internal topological vertex ordering + */ + @Override public boolean addVertex(V v) + { + boolean added = super.addVertex(v); + + if (added) { + // add to the top + ++maxTopoIndex; + topoOrderMap.putVertex(maxTopoIndex, v); + + ++topologyUpdateCount; + } + + return added; + } + + /** + * adds the vertex if it wasn't already in the graph, and puts it either at + * the top or the bottom of the topological ordering, depending on the value + * of addToTop. This may provide useful optimizations for merging + * DirectedAcyclicGraphS that become connected. + * + * @param v + * @param addToTop + * + * @return + */ + public boolean addVertex(V v, boolean addToTop) + { + boolean added = super.addVertex(v); + + if (added) { + int insertIndex; + + // add to the top + if (addToTop) { + insertIndex = ++maxTopoIndex; + } else { + insertIndex = --minTopoIndex; + } + topoOrderMap.putVertex(insertIndex, v); + + ++topologyUpdateCount; + } + return added; + } + + /** + *

Adds the given edge and updates the internal topological order for + * consistency IFF + * + *

    + *
  • there is not already an edge (fromVertex, toVertex) in the graph + *
  • the edge does not induce a cycle in the graph + *
+ *

+ * + * @return null if the edge is already in the graph, else the created edge + * is returned + * + * @throws IllegalArgumentException If either fromVertex or toVertex is not + * a member of the graph + * @throws CycleFoundException if the edge would induce a cycle in the graph + * + * @see Graph#addEdge(Object, Object, Object) + */ + public E addDagEdge(V fromVertex, V toVertex) + throws CycleFoundException + { + Integer lb = topoOrderMap.getTopologicalIndex(toVertex); + Integer ub = topoOrderMap.getTopologicalIndex(fromVertex); + + if ((lb == null) || (ub == null)) { + throw new IllegalArgumentException( + "vertices must be in the graph already!"); + } + + if (lb < ub) { + Set df = new HashSet(); + Set db = new HashSet(); + + // Discovery + Region affectedRegion = new Region(lb, ub); + Visited visited = visitedFactory.getInstance(affectedRegion); + + // throws CycleFoundException if there is a cycle + dfsF(toVertex, df, visited, affectedRegion); + + dfsB(fromVertex, db, visited, affectedRegion); + reorder(df, db, visited); + ++topologyUpdateCount; // if we do a reorder, than the topology has + // been updated + } + + return super.addEdge(fromVertex, toVertex); + } + + /** + * identical to {@link #addDagEdge(Object, Object)}, except an unchecked + * {@link IllegalArgumentException} is thrown if a cycle would have been + * induced by this edge + */ + @Override public E addEdge(V sourceVertex, V targetVertex) + { + E result = null; + try { + result = addDagEdge(sourceVertex, targetVertex); + } catch (CycleFoundException e) { + throw new IllegalArgumentException(e); + } + return result; + } + + /** + *

Adds the given edge and updates the internal topological order for + * consistency IFF + * + *

    + *
  • the given edge is not already a member of the graph + *
  • there is not already an edge (fromVertex, toVertex) in the graph + *
  • the edge does not induce a cycle in the graph + *
+ *

+ * + * @return true if the edge was added to the graph + * + * @throws CycleFoundException if adding an edge (fromVertex, toVertex) to + * the graph would induce a cycle. + * + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addDagEdge(V fromVertex, V toVertex, E e) + throws CycleFoundException + { + if (e == null) { + throw new NullPointerException(); + } else if (containsEdge(e)) { + return false; + } + + Integer lb = topoOrderMap.getTopologicalIndex(toVertex); + Integer ub = topoOrderMap.getTopologicalIndex(fromVertex); + + if ((lb == null) || (ub == null)) { + throw new IllegalArgumentException( + "vertices must be in the graph already!"); + } + + if (lb < ub) { + Set df = new HashSet(); + Set db = new HashSet(); + + // Discovery + Region affectedRegion = new Region(lb, ub); + Visited visited = visitedFactory.getInstance(affectedRegion); + + // throws CycleFoundException if there is a cycle + dfsF(toVertex, df, visited, affectedRegion); + + dfsB(fromVertex, db, visited, affectedRegion); + reorder(df, db, visited); + ++topologyUpdateCount; // if we do a reorder, than the topology has + // been updated + } + + return super.addEdge(fromVertex, toVertex, e); + } + + /** + * identical to {@link #addDagEdge(Object, Object, Object)}, except an + * unchecked {@link IllegalArgumentException} is thrown if a cycle would + * have been induced by this edge + */ + @Override public boolean addEdge(V sourceVertex, V targetVertex, E edge) + { + boolean result; + try { + result = addDagEdge(sourceVertex, targetVertex, edge); + } catch (CycleFoundException e) { + throw new IllegalArgumentException(e); + } + return result; + } + + // note that this can leave holes in the topological ordering, which + // (depending on the TopoOrderMap implementation) can degrade performance + // for certain operations over time + @Override public boolean removeVertex(V v) + { + boolean removed = super.removeVertex(v); + + if (removed) { + Integer topoIndex = topoOrderMap.removeVertex(v); + + // contract minTopoIndex as we are able + if (topoIndex == minTopoIndex) { + while ( + (minTopoIndex < 0) + && (null == topoOrderMap.getVertex(minTopoIndex))) + { + ++minTopoIndex; + } + } + + // contract maxTopoIndex as we are able + if (topoIndex == maxTopoIndex) { + while ( + (maxTopoIndex > 0) + && (null == topoOrderMap.getVertex(maxTopoIndex))) + { + --maxTopoIndex; + } + } + + ++topologyUpdateCount; + } + + return removed; + } + + @Override public boolean removeAllVertices(Collection arg0) + { + boolean removed = super.removeAllVertices(arg0); + + topoOrderMap.removeAllVertices(); + + maxTopoIndex = 0; + minTopoIndex = 0; + + ++topologyUpdateCount; + + return removed; + } + + /** + * Depth first search forward, building up the set (df) of forward-connected + * vertices in the Affected Region + * + * @param vertex the vertex being visited + * @param df the set we are populating with forward connected vertices in + * the Affected Region + * @param visited a simple data structure that lets us know if we already + * visited a node with a given topo index + * @param topoIndexMap for quick lookups, a map from vertex to topo index in + * the AR + * @param ub the topo index of the original fromVertex -- used for cycle + * detection + * + * @throws CycleFoundException if a cycle is discovered + */ + private void dfsF( + V vertex, + Set df, + Visited visited, + Region affectedRegion) + throws CycleFoundException + { + int topoIndex = topoOrderMap.getTopologicalIndex(vertex); + + // Assumption: vertex is in the AR and so it will be in visited + visited.setVisited(topoIndex); + + df.add(vertex); + + for (E outEdge : outgoingEdgesOf(vertex)) { + V nextVertex = getEdgeTarget(outEdge); + Integer nextVertexTopoIndex = + topoOrderMap.getTopologicalIndex(nextVertex); + + if (nextVertexTopoIndex.intValue() == affectedRegion.finish) { + // reset visited + try { + for (V visitedVertex : df) { + visited.clearVisited( + topoOrderMap.getTopologicalIndex(visitedVertex)); + } + } catch (UnsupportedOperationException e) { + // okay, fine, some implementations (ones that automatically + // clear themselves out) don't work this way + } + throw new CycleFoundException(); + } + + // note, order of checks is important as we need to make sure the + // vertex is in the affected region before we check its visited + // status (otherwise we will be causing an + // ArrayIndexOutOfBoundsException). + if (affectedRegion.isIn(nextVertexTopoIndex) + && !visited.getVisited(nextVertexTopoIndex)) + { + dfsF(nextVertex, df, visited, affectedRegion); // recurse + } + } + } + + /** + * Depth first search backward, building up the set (db) of back-connected + * vertices in the Affected Region + * + * @param vertex the vertex being visited + * @param db the set we are populating with back-connected vertices in the + * AR + * @param visited + * @param topoIndexMap + */ + private void dfsB( + V vertex, + Set db, + Visited visited, + Region affectedRegion) + { + // Assumption: vertex is in the AR and so we will get a topoIndex from + // the map + int topoIndex = topoOrderMap.getTopologicalIndex(vertex); + visited.setVisited(topoIndex); + + db.add(vertex); + + for (E inEdge : incomingEdgesOf(vertex)) { + V previousVertex = getEdgeSource(inEdge); + Integer previousVertexTopoIndex = + topoOrderMap.getTopologicalIndex(previousVertex); + + // note, order of checks is important as we need to make sure the + // vertex is in the affected region before we check its visited + // status (otherwise we will be causing an + // ArrayIndexOutOfBoundsException). + if (affectedRegion.isIn(previousVertexTopoIndex) + && !visited.getVisited(previousVertexTopoIndex)) + { + // if prevousVertexTopoIndex != null, the vertex is in the + // Affected Region according to our topoIndexMap + + dfsB(previousVertex, db, visited, affectedRegion); + } + } + } + + @SuppressWarnings("unchecked") + private void reorder(Set df, Set db, Visited visited) + { + List topoDf = new ArrayList(df); + List topoDb = new ArrayList(db); + + Collections.sort(topoDf, topoComparator); + Collections.sort(topoDb, topoComparator); + + // merge these suckers together in topo order + + SortedSet availableTopoIndices = new TreeSet(); + + // we have to cast to the generic type, can't do "new V[size]" in java + // 5; + V [] bigL = (V []) new Object[df.size() + db.size()]; + int lIndex = 0; // this index is used for the sole purpose of pushing + // into + + // the correct index of bigL + + // assume (for now) that we are resetting visited + boolean clearVisited = true; + + for (V vertex : topoDb) { + Integer topoIndex = topoOrderMap.getTopologicalIndex(vertex); + + // add the available indices to the set + availableTopoIndices.add(topoIndex); + + bigL[lIndex++] = vertex; + + if (clearVisited) { // reset visited status if supported + try { + visited.clearVisited(topoIndex); + } catch (UnsupportedOperationException e) { + clearVisited = false; + } + } + } + + for (V vertex : topoDf) { + Integer topoIndex = topoOrderMap.getTopologicalIndex(vertex); + + // add the available indices to the set + availableTopoIndices.add(topoIndex); + bigL[lIndex++] = vertex; + + if (clearVisited) { // reset visited status if supported + try { + visited.clearVisited(topoIndex); + } catch (UnsupportedOperationException e) { + clearVisited = false; + } + } + } + + lIndex = 0; // reusing lIndex + for (Integer topoIndex : availableTopoIndices) { + // assign the indexes to the elements of bigL in order + V vertex = bigL[lIndex++]; // note the post-increment + topoOrderMap.putVertex(topoIndex, vertex); + } + } + + //~ Inner Interfaces ------------------------------------------------------- + + /** + * For performance tuning, an interface for storing the topological ordering + * + * @author gilesp + */ + public interface TopoOrderMapping + extends Serializable + { + /** + * add a vertex at the given topological index. + * + * @param index + * @param vertex + */ + public void putVertex(Integer index, V vertex); + + /** + * get the vertex at the given topological index. + * + * @param index + * + * @return + */ + public V getVertex(Integer index); + + /** + * get the topological index of the given vertex. + * + * @param vertex + * + * @return the index that the vertex is at, or null if the vertex isn't + * in the topological ordering + */ + public Integer getTopologicalIndex(V vertex); + + /** + * remove the given vertex from the topological ordering + * + * @param vertex + * + * @return the index that the vertex was at, or null if the vertex + * wasn't in the topological ordering + */ + public Integer removeVertex(V vertex); + + /** + * remove all vertices from the topological ordering + */ + public void removeAllVertices(); + } + + public interface TopoOrderMappingFactory + { + public TopoOrderMapping getTopoOrderMapping(); + } + + /** + * this interface allows specification of a strategy for marking vertices as + * visited (based on their topological index, so the vertex type isn't part + * of the interface). + */ + public interface Visited + { + /** + * mark the given topological index as visited + * + * @param index the topological index + */ + public void setVisited(int index); + + /** + * has the given topological index been visited? + * + * @param index the topological index + */ + public boolean getVisited(int index); + + /** + * Clear the visited state of the given topological index + * + * @param index + * + * @throws UnsupportedOperationException if the implementation doesn't + * support (or doesn't need) clearance. For example, if the factory + * vends a new instance every time, it is a waste of cycles to clear the + * state after the search of the Affected Region is done, so an + * UnsupportedOperationException *should* be thrown. + */ + public void clearVisited(int index) + throws UnsupportedOperationException; + } + + /** + * interface for a factory that vends Visited implementations + * + * @author gilesp + */ + public interface VisitedFactory + extends Serializable + { + public Visited getInstance(Region affectedRegion); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Note, this is a lazy and incomplete implementation, with assumptions that + * inputs are in the given topoIndexMap + * + * @param + * + * @author gilesp + */ + private static class TopoComparator + implements Comparator, + Serializable + { + /** + */ + private static final long serialVersionUID = 1L; + + private TopoOrderMapping topoOrderMap; + + public TopoComparator(TopoOrderMapping topoOrderMap) + { + this.topoOrderMap = topoOrderMap; + } + + public int compare(V o1, V o2) + { + return topoOrderMap.getTopologicalIndex(o1).compareTo( + topoOrderMap.getTopologicalIndex(o2)); + } + } + + /** + * a dual HashMap implementation + * + * @author gilesp + */ + private class TopoVertexBiMap + implements TopoOrderMapping, + TopoOrderMappingFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final Map topoToVertex = new HashMap(); + private final Map vertexToTopo = new HashMap(); + + public void putVertex(Integer index, V vertex) + { + topoToVertex.put(index, vertex); + vertexToTopo.put(vertex, index); + } + + public V getVertex(Integer index) + { + return topoToVertex.get(index); + } + + public Integer getTopologicalIndex(V vertex) + { + Integer topoIndex = vertexToTopo.get(vertex); + return topoIndex; + } + + public Integer removeVertex(V vertex) + { + Integer topoIndex = vertexToTopo.remove(vertex); + if (topoIndex != null) { + topoToVertex.remove(topoIndex); + } + return topoIndex; + } + + public void removeAllVertices() + { + vertexToTopo.clear(); + topoToVertex.clear(); + } + + public TopoOrderMapping getTopoOrderMapping() + { + return this; + } + } + + /** + * For performance and flexibility uses an ArrayList for topological index + * to vertex mapping, and a HashMap for vertex to topological index mapping. + * + * @author gilesp + */ + public class TopoVertexMap + implements TopoOrderMapping, + TopoOrderMappingFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final List topoToVertex = new ArrayList(); + private final Map vertexToTopo = new HashMap(); + + public void putVertex(Integer index, V vertex) + { + int translatedIndex = translateIndex(index); + + // grow topoToVertex as needed to accommodate elements + while ((translatedIndex + 1) > topoToVertex.size()) { + topoToVertex.add(null); + } + + topoToVertex.set(translatedIndex, vertex); + vertexToTopo.put(vertex, index); + } + + public V getVertex(Integer index) + { + return topoToVertex.get(translateIndex(index)); + } + + public Integer getTopologicalIndex(V vertex) + { + return vertexToTopo.get(vertex); + } + + public Integer removeVertex(V vertex) + { + Integer topoIndex = vertexToTopo.remove(vertex); + if (topoIndex != null) { + topoToVertex.set(translateIndex(topoIndex), null); + } + return topoIndex; + } + + public void removeAllVertices() + { + vertexToTopo.clear(); + topoToVertex.clear(); + } + + public TopoOrderMapping getTopoOrderMapping() + { + return this; + } + + /** + * We translate the topological index to an ArrayList index. We have to + * do this because topological indices can be negative, and we want to + * do it because we can make better use of space by only needing an + * ArrayList of size |AR|. + * + * @param unscaledIndex + * + * @return the ArrayList index + */ + private final int translateIndex(int index) + { + if (index >= 0) { + return 2 * index; + } + return -1 * ((index * 2) - 1); + } + } + + /** + * Region is an *inclusive* range of indices. Esthetically displeasing, but + * convenient for our purposes. + * + * @author gilesp + */ + public static class Region + implements Serializable + { + /** + */ + private static final long serialVersionUID = 1L; + + public final int start; + public final int finish; + + public Region(int start, int finish) + { + if (start > finish) { + throw new IllegalArgumentException( + "(start > finish): invariant broken"); + } + this.start = start; + this.finish = finish; + } + + public int getSize() + { + return (finish - start) + 1; + } + + public boolean isIn(int index) + { + return (index >= start) && (index <= finish); + } + } + + /** + * This implementation is close to the performance of VisitedArrayListImpl, + * with 1/8 the memory usage. + * + * @author perfecthash + */ + public static class VisitedBitSetImpl + implements Visited, + VisitedFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final BitSet visited = new BitSet(); + + private Region affectedRegion; + + public Visited getInstance(Region affectedRegion) + { + this.affectedRegion = affectedRegion; + + return this; + } + + public void setVisited(int index) + { + visited.set(translateIndex(index), true); + } + + public boolean getVisited(int index) + { + return visited.get(translateIndex(index)); + } + + public void clearVisited(int index) + throws UnsupportedOperationException + { + visited.clear(translateIndex(index)); + } + + /** + * We translate the topological index to an ArrayList index. We have to + * do this because topological indices can be negative, and we want to + * do it because we can make better use of space by only needing an + * ArrayList of size |AR|. + * + * @param unscaledIndex + * + * @return the ArrayList index + */ + private int translateIndex(int index) + { + return index - affectedRegion.start; + } + } + + /** + * This implementation seems to offer the best performance in most cases. It + * grows the internal ArrayList as needed to be as large as |AR|, so it will + * be more memory intensive than the HashSet implementation, and unlike the + * Array implementation, it will hold on to that memory (it expands, but + * never contracts). + * + * @author gilesp + */ + public static class VisitedArrayListImpl + implements Visited, + VisitedFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final List visited = new ArrayList(); + + private Region affectedRegion; + + public Visited getInstance(Region affectedRegion) + { + // Make sure visited is big enough + int minSize = (affectedRegion.finish - affectedRegion.start) + 1; + /* plus one because the region range is inclusive of both indices */ + + while (visited.size() < minSize) { + visited.add(Boolean.FALSE); + } + + this.affectedRegion = affectedRegion; + + return this; + } + + public void setVisited(int index) + { + visited.set(translateIndex(index), Boolean.TRUE); + } + + public boolean getVisited(int index) + { + Boolean result = null; + + result = visited.get(translateIndex(index)); + + return result; + } + + public void clearVisited(int index) + throws UnsupportedOperationException + { + visited.set(translateIndex(index), Boolean.FALSE); + } + + /** + * We translate the topological index to an ArrayList index. We have to + * do this because topological indices can be negative, and we want to + * do it because we can make better use of space by only needing an + * ArrayList of size |AR|. + * + * @param unscaledIndex + * + * @return the ArrayList index + */ + private int translateIndex(int index) + { + return index - affectedRegion.start; + } + } + + /** + * This implementation doesn't seem to perform as well, though I can imagine + * circumstances where it should shine (lots and lots of vertices). It also + * should have the lowest memory footprint as it only uses storage for + * indices that have been visited. + * + * @author gilesp + */ + public static class VisitedHashSetImpl + implements Visited, + VisitedFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final Set visited = new HashSet(); + + public Visited getInstance(Region affectedRegion) + { + visited.clear(); + return this; + } + + public void setVisited(int index) + { + visited.add(index); + } + + public boolean getVisited(int index) + { + return visited.contains(index); + } + + public void clearVisited(int index) + throws UnsupportedOperationException + { + throw new UnsupportedOperationException(); + } + } + + /** + * This implementation, somewhat to my surprise, is slower than the + * ArrayList version, probably due to its reallocation of the underlying + * array for every topology reorder that is required. + * + * @author gilesp + */ + public static class VisitedArrayImpl + implements Visited, + VisitedFactory + { + /** + */ + private static final long serialVersionUID = 1L; + + private final boolean [] visited; + + private final Region region; + + /** + * Constructs empty factory instance + */ + public VisitedArrayImpl() + { + this(null); + } + + public VisitedArrayImpl(Region region) + { + if (region == null) { // make empty instance + this.visited = null; + this.region = null; + } else { // fill in the needed pieces + this.region = region; + + // initialized to all false by default + visited = new boolean[region.getSize()]; + } + } + + public Visited getInstance(Region affectedRegion) + { + return new VisitedArrayImpl(affectedRegion); + } + + public void setVisited(int index) + { + try { + visited[index - region.start] = true; + } catch (ArrayIndexOutOfBoundsException e) { + /* + log.error("Visited set operation out of region boundaries", e); + */ + throw e; + } + } + + public boolean getVisited(int index) + { + try { + return visited[index - region.start]; + } catch (ArrayIndexOutOfBoundsException e) { + /* + log.error("Visited set operation out of region boundaries", e); + */ + throw e; + } + } + + public void clearVisited(int index) + throws UnsupportedOperationException + { + throw new UnsupportedOperationException(); + } + } + + /** + * Exception used in dfsF when a cycle is found + * + * @author gilesp + */ + public static class CycleFoundException + extends Exception + { + private static final long serialVersionUID = 5583471522212552754L; + } + + /** + * iterator which follows topological order + * + * @author gilesp + */ + private class TopoIterator + implements Iterator + { + private int currentTopoIndex; + private final long updateCountAtCreation; + private Integer nextIndex = null; + + public TopoIterator() + { + updateCountAtCreation = topologyUpdateCount; + currentTopoIndex = minTopoIndex - 1; + } + + public boolean hasNext() + { + if (updateCountAtCreation != topologyUpdateCount) { + throw new ConcurrentModificationException(); + } + + nextIndex = getNextIndex(); + return nextIndex != null; + } + + public V next() + { + if (updateCountAtCreation != topologyUpdateCount) { + throw new ConcurrentModificationException(); + } + + if (nextIndex == null) { + // find nextIndex + nextIndex = getNextIndex(); + } + if (nextIndex == null) { + throw new NoSuchElementException(); + } + currentTopoIndex = nextIndex; + nextIndex = null; + return topoOrderMap.getVertex(currentTopoIndex); //topoToVertex.get(currentTopoIndex); + } + + public void remove() + { + if (updateCountAtCreation != topologyUpdateCount) { + throw new ConcurrentModificationException(); + } + + V vertexToRemove = null; + if (null + != (vertexToRemove = + topoOrderMap.getVertex( + currentTopoIndex))) + { + topoOrderMap.removeVertex(vertexToRemove); + } else { + // should only happen if next() hasn't been called + throw new IllegalStateException(); + } + } + + private Integer getNextIndex() + { + for (int i = currentTopoIndex + 1; i <= maxTopoIndex; i++) { + if (null != topoOrderMap.getVertex(i)) { + return i; + } + } + return null; + } + } +} + +// End DirectedAcyclicGraph.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java new file mode 100644 index 0000000..433d1a1 --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java @@ -0,0 +1,93 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceComparator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +/** + * This interface distinguishes between Equivalence sets. + * + *

It is similar, in concept, to the Object.hashcode() and Object.equals() + * methods, but instead of checking whether two objects are equal, it is used to + * check whether they are part of the same Equivalence group, where the + * definition of an "equivalence" is defined by the implementation of this + * interface. + * + *

A specific usage of it is shown below, but it may be used outside of the + * graph-theory class library. + * + *

In Isomorphism, edges/vertexes matching may relay on none/some/all of the + * vertex/edge properties. For example, if a vertex representing a person + * contains two properties: gender(male/female) and person name(string), we can + * decide that to check isomorphism in vertex groups of gender only. Meaning if + * this is the graph: + * + *

(male,"Don")---->(female,"Dana")--->(male,"John") + * + *

if there is no equivalence set at all , this graph can be described as: + * (1)---->(2)---->(3) + * + *

if the equivalence set is determined only by the gender property : + * (male)---->(female)---->(male) + * + *

and if it is determined by both properties: (the original figure) The + * isomorphism inspection may return different result according to this choice. + * If the other graph is: (male,"Don")--->(male,"Sunny")---->(male,"Jo") In no + * eq.set they are Isomorphic, but for the two other cases they are not. Other + * examples: Nodes with the same degree, Edges with the same weight, Graphs with + * the same number of nodes and edges. + * + * @param the type of the elements in the set + * @param the type of the context the element is compared against, e.g. a + * Graph + * + * @author Assaf + * @since Jul 15, 2005 + */ +public interface EquivalenceComparator +{ + //~ Methods ---------------------------------------------------------------- + + public boolean equivalenceCompare( + E arg1, + E arg2, + C context1, + C context2); + + public int equivalenceHashcode(E arg1, C context); +} + +// End EquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java new file mode 100644 index 0000000..4f7871b --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java @@ -0,0 +1,71 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceComparatorChain.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +/** + * A container of comparators, which are tested in a chain until the first + * result can be supplied. It implements the EquivalenceComparator, so chains + * can include other chains. The first check will use the current comparator and + * not the next one. So, make sure to use the one which has better performance + * first. (This class follows the "Composite" design-pattern). + * + * @param the type of the elements in the set + * @param the type of the context the element is compared against, e.g. a + * Graph + * + * @author Assaf + * @since Jul 22, 2005 + */ +public interface EquivalenceComparatorChain + extends EquivalenceComparator +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Adds a comparator which will also test equivalence. For + * equivalenceCompare(), the return value is a logical AND of the two + * comparators. The first check will use the first comparator before the + * next one. Make sure to put the one which has better performance first. + * For equivalenceHashcode(), the resulting hashes will be rehashed + * together. This method may be used multiple times to create a long "chain" + * of comparators. + */ + public void appendComparator(EquivalenceComparator comparatorAfter); +} + +// End EquivalenceComparatorChain.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java new file mode 100644 index 0000000..b6f9fd3 --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java @@ -0,0 +1,167 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceComparatorChainBase.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: EquivalenceComparatorChainBase.java 485 2006-06-26 09:12:14Z perfecthash + * $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +import java.util.*; + + +/** + * This class implements comparator chaining. + * + *

Usage examples: + *

  • graph-theory, node equivalence: You can create a comparator for + * the inDegree of a node, another for the total weight of outDegree edges, and + * a third which checks the business content of the node. You know that the + * first topological comparators has dozens of different groups, but the + * buisness comparator has only two, and they are hard to check . The best + * performance will be gained by: + * + *
    + *

    EquivalenceComparatorChainBase eqChain = new + * EquivalenceComparatorChainBase(fastNodesDegreeComparator); + * + *

    eqChain.addComparatorAfter(ABitSlowerEdgeWeightComparator); + * + *

    eqChain.addComparatorAfter(slowestBuisnessContentsComparator); + *

    + * + * @param the type of the elements in the set + * @param the type of the context the element is compared against, e.g. a + * Graph + * + * @author Assaf + * @since Jul 22, 2005 + */ +public class EquivalenceComparatorChainBase + implements EquivalenceComparatorChain +{ + //~ Instance fields -------------------------------------------------------- + + private List> chain; + + //~ Constructors ----------------------------------------------------------- + + /** + */ + public EquivalenceComparatorChainBase( + EquivalenceComparator firstComaparator) + { + this.chain = + new LinkedList>(); + this.chain.add(firstComaparator); + } + + //~ Methods ---------------------------------------------------------------- + + /* (non-Javadoc) + * @see + * + * + * + * + * + * org.jgrapht.experimental.equivalence.EquivalenceComparatorChain#addComparatorAfter(org.jgrapht.experimental.equivalence.EquivalenceComparator) + */ + @SuppressWarnings("unchecked") + public void appendComparator(EquivalenceComparator comparatorAfter) + { + if (comparatorAfter != null) { + this.chain.add(comparatorAfter); + } + } + + /** + * Implements logical AND between the comparators results. Iterates through + * the comparators chain until one of them returns false. If none returns + * false, this method returns true. + * + * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, + * Object) + */ + public boolean equivalenceCompare( + E arg1, + E arg2, + C context1, + C context2) + { + for ( + EquivalenceComparator currentComparator + : this.chain) + { + if (!currentComparator.equivalenceCompare( + arg1, + arg2, + context1, + context2)) + { + return false; + } + } + return true; + } + + /** + * Rehashes the concatenation of the results of all single hashcodes. + * + * @see EquivalenceComparator#equivalenceHashcode(Object, Object) + */ + public int equivalenceHashcode(E arg1, C context) + { + StringBuffer hashStringBuffer = new StringBuffer(); + for ( + ListIterator> iter = + this.chain.listIterator(); + iter.hasNext();) + { + EquivalenceComparator currentComparator = + iter.next(); + int currentHashCode = + currentComparator.equivalenceHashcode(arg1, context); + hashStringBuffer.append(currentHashCode); + + // add a delimeter only if needed for next + if (iter.hasNext()) { + hashStringBuffer.append('+'); + } + } + return hashStringBuffer.toString().hashCode(); + } +} + +// End EquivalenceComparatorChainBase.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java b/wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java new file mode 100644 index 0000000..43b976a --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java @@ -0,0 +1,206 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceSet.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +import java.util.*; + + +/** + * EquivalenceSet is a Set of elements which have been determined to be + * equivalent using EquivalenceComparator. The class makes sure the set size + * will be one or more. + *
  • The group can only be created using the factory method + * createGroupWithElement(). + *
  • The equals and hashcode of a group uses the EquivalenceComparator on one + * of the group members, thus it is actually checking whether the "other" is in + * the same group. + * + * @param the type of the elements in the set + * @param the type of the context the element is compared against, e.g. a + * Graph + * + * @author Assaf + * @since Jul 21, 2005 + */ +public class EquivalenceSet +{ + //~ Instance fields -------------------------------------------------------- + + /** + * The comparator used to define the group + */ + protected EquivalenceComparator eqComparator; + protected C comparatorContext; + + /** + * Contains the current elements of the group + */ + protected Set elementsSet; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructs a new EquivalenceSet, filled with the aElement parameter and a + * reference to the comparator which is used. + */ + public EquivalenceSet( + E aElement, + EquivalenceComparator aEqComparator, + C aComparatorContext) + { + this.eqComparator = aEqComparator; + this.comparatorContext = aComparatorContext; + + this.elementsSet = new HashSet(); + this.elementsSet.add(aElement); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns an arbitrary object from the group. There is no guarantee as to + * which will be returned, and whether the same will be returned on the next + * call. + */ + public E getRepresentative() + { + return elementsSet.iterator().next(); + } + + public C getContext() + { + return this.comparatorContext; + } + + public int size() + { + return elementsSet.size(); + } + + /** + * Adds an element to the group. It does not check it for equivalance . You + * must make sure it does, using equals(). + */ + public void add(E element) + { + this.elementsSet.add(element); + } + + public boolean equivalentTo(E aOther, C aOtherContext) + { + boolean result = + this.eqComparator.equivalenceCompare( + this.getRepresentative(), + aOther, + this.comparatorContext, + aOtherContext); + return result; + } + + /** + * Uses the equivalenceCompare() of the comparator to compare a + * representation of this group, taken using this.getRepresentative(), and a + * representation of the other object, which may be the object itself, or, + * if it is an equivalence group too, other.getRepresentative() + */ + // FIXME REVIEW hb 26-Jan-2006: I think throwing the exception is kind of + // odd, + // - it feels like violating the contract of Object.equals() + // From what I understand, comparing any object to any other object should + // be + // possible at all times and simply return false if they are not equal. + // Uncomparable objects beeing unequal. + // Suggestion: remove the exception, at best, test on this specific class + // and + // write a warning or some such. + + @SuppressWarnings("unchecked") + public boolean equals(Object other) + { + E otherRepresentative = null; + C otherContext = null; + if (other instanceof EquivalenceSet) { + otherRepresentative = + ((EquivalenceSet) other).getRepresentative(); + otherContext = ((EquivalenceSet) other).getContext(); + } else { + throw new ClassCastException( + "can check equal() only of EqualityGroup"); + } + + boolean result = + this.eqComparator.equivalenceCompare( + this.getRepresentative(), + otherRepresentative, + this.comparatorContext, + otherContext); + return result; + } + + /** + * Uses a representative to calculate the group hashcode using + * equivalenceHashcode(). + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() + { + int result = + this.eqComparator.equivalenceHashcode( + this.getRepresentative(), + this.comparatorContext); + return result; + } + + public String toString() + { + return "Eq.Group=" + this.elementsSet.toString(); + } + + /** + * Returns the elements of the group. The order of the elements in the + * returned array is not guaranteed. In other words, two calls to the same + * object may return different order. + */ + public Object [] toArray() + { + return this.elementsSet.toArray(); + } +} + +// End EquivalenceSet.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java b/wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java new file mode 100644 index 0000000..0b3aeee --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java @@ -0,0 +1,262 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceSetCreator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +import java.util.*; + + +/** + * FIXME Document me. + * + * @param the type of the elements in the set + * @param the type of the context the element is compared against, e.g. a + * Graph TODO hb 060208: REVIEW: Using an array for aElementsArray causes + * problems with generics elsewhere - changed to List? + * + * @author Assaf + * @since Jul 21, 2005 + */ +public class EquivalenceSetCreator +{ + //~ Static fields/initializers --------------------------------------------- + + private static final EqGroupSizeComparator groupSizeComparator = + new EqGroupSizeComparator(); + + //~ Methods ---------------------------------------------------------------- + + /** + * Checks for equivalance groups in the aElementsArray. Returns an ordered + * array of them, where the smallest one is the first in the array. + * + * @param aElementsArray + * @param aEqComparator + * + * @deprecated To improve type-safety when using generics, use {@link + * #createEqualityGroupOrderedArray(Collection, EquivalenceComparator, + * Object)} + */ + @Deprecated public static EquivalenceSet [] + createEqualityGroupOrderedArray( + EE [] aElementsArray, + EquivalenceComparator aEqComparator, + CC aContext) + { + return (createEqualityGroupOrderedArray( + Arrays.asList(aElementsArray), + aEqComparator, + aContext)); + // ArrayList> arrayList = new + // ArrayList>(); + // + // HashMap>> map + // = createEqualityGroupMap(aElementsArray, aEqComparator, + // aContext); // each of the map values is a list with one or + // more groups in it. // Object[] array = map.values().toArray(); + // // for (int i = 0; i < array.length; i++) // { // List list = + // (List)array[i]; + // + // for (List> list : + // map.values() ) { for (EquivalenceSet + // eSet : list ) { arrayList.add( eSet ); } } + // + // + // now we got all the eq. groups in an array list. we need to sort + // // them EquivalenceSet [] resultArray = new EquivalenceSet + // [arrayList.size()]; arrayList.toArray(resultArray); + // Arrays.sort(resultArray, groupSizeComparator); return + // resultArray; + } + + /** + * Checks for equivalance groups in the aElementsArray. Returns an ordered + * array of them, where the smallest one is the first in the array. + * + * @param elements + * @param aEqComparator TODO hb 060208: Using an array for aElementsArray + * causes problems with generics elsewhere - change to List? + */ + public static EquivalenceSet [] createEqualityGroupOrderedArray( + Collection elements, + EquivalenceComparator aEqComparator, + CC aContext) + { + ArrayList> arrayList = + new ArrayList>(); + + HashMap>> map = + createEqualityGroupMap(elements, aEqComparator, aContext); + // each of the map values is a list with one or more groups in it. + // Object[] array = map.values().toArray(); + // for (int i = 0; i < array.length; i++) + // { + // List list = (List)array[i]; + + for (List> list : map.values()) { + for (EquivalenceSet eSet : list) { + arrayList.add(eSet); + } + } + + // now we got all the eq. groups in an array list. we need to sort + // them + EquivalenceSet [] resultArray = new EquivalenceSet[arrayList.size()]; + arrayList.toArray(resultArray); + Arrays.sort(resultArray, groupSizeComparator); + return resultArray; + } + + /** + * The data structure we use to store groups is a map, where the key is + * eqGroupHashCode, and the value is list, containing one or more eqGroup + * which match this hash. + * + * @param elements + * @param aEqComparator + * + * @return a hashmap with key=group hashcode , value = list of eq.groups + * which match that hash. TODO hb 060208: Using an array for aElementsArray + * causes problems with generics elsewhere - change to List? + */ + private static HashMap>> createEqualityGroupMap( + Collection elements, + EquivalenceComparator aEqComparator, + CC aComparatorContext) + { + HashMap>> equalityGroupMap = + new HashMap>>( + elements.size()); + + for (EE curentElement : elements) { + int hashcode = + aEqComparator.equivalenceHashcode( + curentElement, + aComparatorContext); + List> list = + equalityGroupMap.get(Integer.valueOf(hashcode)); + + // determine the type of value. It can be null(no value yet) , + // or a list of EquivalenceSet + + if (list == null) { + // create list with one element in it + list = new LinkedList>(); + list.add( + new EquivalenceSet( + curentElement, + aEqComparator, + aComparatorContext)); + + // This is the first one .add it to the map , in an eqGroup + equalityGroupMap.put(Integer.valueOf(hashcode), list); + } else { + boolean eqWasFound = false; + + // we need to check the groups in the list. If none are good, + // create a new one + for (EquivalenceSet eqGroup : list) { + if (eqGroup.equivalentTo( + curentElement, + aComparatorContext)) + { + // add it to the list and break + eqGroup.add(curentElement); + eqWasFound = true; + break; + } + } + + // if no match was found add it to the list as a new group + if (!eqWasFound) { + list.add( + new EquivalenceSet( + curentElement, + aEqComparator, + aComparatorContext)); + } + } + } + + return equalityGroupMap; + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Functor used to order groups by size (number of elements in the group) + * from the smallest to the biggest. If they have the same size, uses the + * hashcode of the group to compare from the smallest to the biggest. Note + * that it is inconsistent with equals(). See Object.equals() javadoc. + * + * @author Assaf + * @since Jul 22, 2005 + */ + private static class EqGroupSizeComparator + implements Comparator + { + /** + * compare by size , then (if size equal) by hashcode + * + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @SuppressWarnings("unchecked") + public int compare(EquivalenceSet arg1, EquivalenceSet arg2) + { + int eqGroupSize1 = arg1.size(); + int eqGroupSize2 = arg2.size(); + if (eqGroupSize1 > eqGroupSize2) { + return 1; + } else if (eqGroupSize1 < eqGroupSize2) { + return -1; + } else { // size equal , compare hashcodes + int eqGroupHash1 = arg1.hashCode(); + int eqGroupHash2 = arg2.hashCode(); + if (eqGroupHash1 > eqGroupHash2) { + return 1; + } else if (eqGroupHash1 < eqGroupHash2) { + return -1; + } else { + return 0; + } + } + } + } +} + +// End EquivalenceSetCreator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java b/wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java new file mode 100644 index 0000000..43c9afa --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java @@ -0,0 +1,80 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * UniformEquivalenceComparator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.equivalence; + +/** + * This Equivalence comparator acts as if all elements are in one big global + * equivalence class. Useful when a comparator is needed, but there is no + * important difference between the elements. equivalenceCompare() always return + * true; equivalenceHashcode() always returns 0. + * + * @author Assaf + * @since Jul 21, 2005 + */ +public class UniformEquivalenceComparator + implements EquivalenceComparator +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Always returns true. + * + * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, + * Object) + */ + public boolean equivalenceCompare( + E arg1, + E arg2, + C context1, + C context2) + { + return true; + } + + /** + * Always returns 0. + * + * @see EquivalenceComparator#equivalenceHashcode(Object, Object) + */ + public int equivalenceHashcode(E arg1, C context) + { + return 0; + } +} + +// End UniformEquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/package.html b/wdl/org/jgrapht/experimental/equivalence/package.html new file mode 100644 index 0000000..dbc6049 --- /dev/null +++ b/wdl/org/jgrapht/experimental/equivalence/package.html @@ -0,0 +1,6 @@ + + + +Classes which enable working with Equivalence Sets. + + diff --git a/wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java b/wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java new file mode 100644 index 0000000..d60683c --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java @@ -0,0 +1,423 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * AbstractExhaustiveIsomorphismInspector.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: AbstractExhaustiveIsomorphismInspector.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.experimental.equivalence.*; +import org.jgrapht.experimental.permutation.*; +import org.jgrapht.util.*; + + +/** + * Abstract base for isomorphism inspectors which exhaustively test the possible + * mappings between graphs. The current algorithms do not support graphs with + * multiple edges (Multigraph / Pseudograph). For the maintainer: The reason is + * the use of GraphOrdering which currently does not support all graph types. + * + * @author Assaf Lehr + * @since May 20, 2005 ver5.3 + */ +abstract class AbstractExhaustiveIsomorphismInspector + implements GraphIsomorphismInspector +{ + //~ Static fields/initializers --------------------------------------------- + + public static EquivalenceComparator + edgeDefaultIsomorphismComparator = + new UniformEquivalenceComparator(); + public static EquivalenceComparator + vertexDefaultIsomorphismComparator = + new UniformEquivalenceComparator(); + + //~ Instance fields -------------------------------------------------------- + + protected EquivalenceComparator> + edgeComparator; + protected EquivalenceComparator> + vertexComparator; + + protected Graph graph1; + protected Graph graph2; + + private PrefetchIterator nextSupplier; + + // kept as member, to ease computations + private GraphOrdering lableGraph1; + private LinkedHashSet graph1VertexSet; + private LinkedHashSet graph2EdgeSet; + private CollectionPermutationIter vertexPermuteIter; + private Set currVertexPermutation; // filled every iteration, used in the + + //~ Constructors ----------------------------------------------------------- + + // result relation. + + /** + * @param graph1 + * @param graph2 + * @param vertexChecker eq. group checker for vertexes. If null, + * UniformEquivalenceComparator will be used as default (always return true) + * @param edgeChecker eq. group checker for edges. If null, + * UniformEquivalenceComparator will be used as default (always return true) + */ + public AbstractExhaustiveIsomorphismInspector( + Graph graph1, + Graph graph2, + + // XXX hb 060128: FOllowing parameter may need Graph + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + this.graph1 = graph1; + this.graph2 = graph2; + + if (vertexChecker != null) { + this.vertexComparator = vertexChecker; + } else { + this.vertexComparator = vertexDefaultIsomorphismComparator; + } + + // Unlike vertexes, edges have better performance, when not tested for + // Equivalence, so if the user did not supply one, use null + // instead of edgeDefaultIsomorphismComparator. + + if (edgeChecker != null) { + this.edgeComparator = edgeChecker; + } + + init(); + } + + /** + * Constructor which uses the default comparators. + * + * @param graph1 + * @param graph2 + * + * @see #AbstractExhaustiveIsomorphismInspector(Graph,Graph,EquivalenceComparator,EquivalenceComparator) + */ + public AbstractExhaustiveIsomorphismInspector( + Graph graph1, + Graph graph2) + { + this( + graph1, + graph2, + edgeDefaultIsomorphismComparator, + vertexDefaultIsomorphismComparator); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Inits needed data-structures , among them: + *
  • LabelsGraph which is a created in the image of graph1 + *
  • vertexPermuteIter which is created after the vertexes were divided to + * equivalence groups. This saves order-of-magnitude in performance, because + * the number of possible permutations dramatically decreases. + * + *

    for example: if the eq.group are even/odd - only two groups. A graph + * with consist of 10 nodes of which 5 are even , 5 are odd , will need to + * test 5!*5! (14,400) instead of 10! (3,628,800). + * + *

    besides the EquivalenceComparator`s supplied by the user, we also use + * predefined topological comparators. + */ + private void init() + { + this.nextSupplier = + new PrefetchIterator( + + // XXX hb 280106: I don't understand this warning, yet :-) + new NextFunctor()); + + this.graph1VertexSet = new LinkedHashSet(this.graph1.vertexSet()); + + // vertexPermuteIter will be null, if there is no match + this.vertexPermuteIter = + createPermutationIterator( + this.graph1VertexSet, + this.graph2.vertexSet()); + + this.lableGraph1 = + new GraphOrdering( + this.graph1, + this.graph1VertexSet, + this.graph1.edgeSet()); + + this.graph2EdgeSet = new LinkedHashSet(this.graph2.edgeSet()); + } + + /** + * Creates the permutation iterator for vertexSet2 . The subclasses may make + * either cause it to depend on equality groups or use vertexSet1 for it. + * + * @param vertexSet1 [i] may be reordered + * @param vertexSet2 [i] may not. + * + * @return permutation iterator + */ + protected abstract CollectionPermutationIter createPermutationIterator( + Set vertexSet1, + Set vertexSet2); + + /** + *

    1. Creates a LabelsGraph of graph1 which will serve as a source to all + * the comparisons which will follow. + * + *

    2. extract the edge array of graph2; it will be permanent too. + * + *

    3. for each permutation of the vertexes of graph2, test : + * + *

    3.1. vertices + * + *

    3.2. edges (in labelsgraph) + * + *

    Implementation Notes and considerations: Let's consider a trivial + * example: graph of strings "A","B","C" with two edges A->B,B->C. Let's + * assume for this example that the vertex comparator always returns true, + * meaning String value does not matter, only the graph structure does. So + * "D" "E" "A" with D->E->A will be isomorphic , but "A","B,"C"with + * A->B,A->C will not. + * + *

    First let's extract the important info for isomorphism from the graph. + * We don't care what the vertexes are, we care that there are 3 of them + * with edges from first to second and from second to third. So the source + * LabelsGraph will be: vertexes:[1,2,3] edges:[[1->2],[2->3]] Now we will + * do several permutations of D,E,A. A few examples: D->E , E->A + * [1,2,3]=[A,D,E] so edges are: 2->3 , 3->1 . does it match the source? NO. + * [1,2,3]=[D,A,E] so edges are: 1->3 , 3->2 . no match either. + * [1,2,3]=[D,E,A] so edges are: 1->2 , 2->3 . MATCH FOUND ! Trivial + * algorithm: We will iterate on all permutations + * [abc][acb][bac][bca][cab][cba]. (n! of them,3!=6) For each, first compare + * vertexes using the VertexComparator(always true). Then see that the edges + * are in the exact order 1st->2nd , 2nd->3rd. If we found a match stop and + * return true, otherwise return false; we will compare vetices and edges by + * their order (1st,2nd,3rd,etc) only. Two graphs are the same, by this + * order, if: 1. for each i, sourceVertexArray[i] is equivalent to + * targetVertexArray[i] 2. for each vertex, the edges which start in it (it + * is the source) goes to the same ordered vertex. For multiple ones, count + * them too. + * + * @return IsomorphismRelation for a permutation found, or null if no + * permutation was isomorphic + */ + private IsomorphismRelation findNextIsomorphicGraph() + { + boolean result = false; + IsomorphismRelation resultRelation = null; + if (this.vertexPermuteIter != null) { + // System.out.println("Souce LabelsGraph="+this.lableGraph1); + while (this.vertexPermuteIter.hasNext()) { + currVertexPermutation = this.vertexPermuteIter.getNextSet(); + + // compare vertexes + if (!areVertexSetsOfTheSameEqualityGroup( + this.graph1VertexSet, + currVertexPermutation)) + { + continue; // this one is not iso, so try the next one + } + + // compare edges + GraphOrdering currPermuteGraph = + new GraphOrdering( + this.graph2, + currVertexPermutation, + this.graph2EdgeSet); + + // System.out.println("target LablesGraph="+currPermuteGraph); + if (this.lableGraph1.equalsByEdgeOrder(currPermuteGraph)) { + // create result object. + resultRelation = + new IsomorphismRelation( + new ArrayList(graph1VertexSet), + new ArrayList(currVertexPermutation), + graph1, + graph2); + + // if the edge comparator exists, check equivalence by it + boolean edgeEq = + areAllEdgesEquivalent( + resultRelation, + this.edgeComparator); + if (edgeEq) // only if equivalent + + { + result = true; + break; + } + } + } + } + + if (result == true) { + return resultRelation; + } else { + return null; + } + } + + /** + * Will be called on every two sets of vertexes returned by the permutation + * iterator. From findNextIsomorphicGraph(). Should make sure that the two + * sets are euqivalent. Subclasses may decide to implements it as an always + * true methods only if they make sure that the permutationIterator will + * always be already equivalent. + * + * @param vertexSet1 FIXME Document me + * @param vertexSet2 FIXME Document me + */ + protected abstract boolean areVertexSetsOfTheSameEqualityGroup( + Set vertexSet1, + Set vertexSet2); + + /** + * For each edge in g1, get the Correspondence edge and test the pair. + * + * @param resultRelation + * @param edgeComparator if null, always return true. + */ + protected boolean areAllEdgesEquivalent( + IsomorphismRelation resultRelation, + EquivalenceComparator> edgeComparator) + { + boolean checkResult = true; + + if (edgeComparator == null) { + // nothing to check + return true; + } + + try { + Set edgeSet = this.graph1.edgeSet(); + + for (E currEdge : edgeSet) { + E correspondingEdge = + resultRelation.getEdgeCorrespondence(currEdge, true); + + // if one edge test fail , fail the whole method + if (!edgeComparator.equivalenceCompare( + currEdge, + correspondingEdge, + this.graph1, + this.graph2)) + { + checkResult = false; + break; + } + } + } catch (IllegalArgumentException illegal) { + checkResult = false; + } + + return checkResult; + } + + /** + * return nextElement() casted as IsomorphismRelation + */ + public IsomorphismRelation nextIsoRelation() + { + return next(); + } + + /** + * Efficiency: The value is known after the first check for isomorphism + * activated on this class and returned there after in O(1). If called on a + * new ("virgin") class, it activates 1 iso-check. + * + * @return true iff the two graphs are isomorphic + */ + public boolean isIsomorphic() + { + return !(this.nextSupplier.isEnumerationStartedEmpty()); + } + + /* (non-Javadoc) + * @see java.util.Enumeration#hasMoreElements() + */ + public boolean hasNext() + { + boolean result = this.nextSupplier.hasMoreElements(); + + return result; + } + + /** + * @see java.util.Iterator#next() + */ + public IsomorphismRelation next() + { + return this.nextSupplier.nextElement(); + } + + /* (non-Javadoc) + * @see java.util.Iterator#remove() + */ + public void remove() + { + throw new UnsupportedOperationException( + "remove() method is not supported in AdaptiveIsomorphismInspectorFactory." + + " There is no meaning to removing an isomorphism result."); + } + + //~ Inner Classes ---------------------------------------------------------- + + private class NextFunctor + implements PrefetchIterator.NextElementFunctor + { + public IsomorphismRelation nextElement() + throws NoSuchElementException + { + IsomorphismRelation resultRelation = findNextIsomorphicGraph(); + if (resultRelation != null) { + return resultRelation; + } else { + throw new NoSuchElementException( + "IsomorphismInspector does not have any more elements"); + } + } + } +} + +// End AbstractExhaustiveIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java b/wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java new file mode 100644 index 0000000..1fca285 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java @@ -0,0 +1,268 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * AdaptiveIsomorphismInspectorFactory.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: AdaptiveIsomorphismInspectorFactory.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import org.jgrapht.*; +import org.jgrapht.experimental.equivalence.*; +import org.jgrapht.graph.*; + + +/** + * This class serves as a factory for GraphIsomorphismInspector concrete + * implementations. It can be used in two ways: + *

  • You can can let this class to determine what is the most efficient + * algorithm for your graph. + *
  • You can specify the type of your graph (planar / tree / other) and save + * this class the graph-checking time. + * + *

    Note that the concrete implementations are package-private and should not + * be created directly. If you are the maintainer of the package, you can add + * new implementation classes, and add them to the "check-list". The current + * algorithms do not support graphs with multiple edges (Multigraph / + * Pseudograph) + * + * @author Assaf + * @see GraphIsomorphismInspector + * @since Jul 17, 2005 + */ +public class AdaptiveIsomorphismInspectorFactory +{ + //~ Static fields/initializers --------------------------------------------- + + public static final int GRAPH_TYPE_ARBITRARY = 0; + public static final int GRAPH_TYPE_PLANAR = 1; + public static final int GRAPH_TYPE_TREE = 2; + public static final int GRAPH_TYPE_MULTIGRAPH = 3; + + //~ Methods ---------------------------------------------------------------- + + /** + * Creates a new inspector, letting this class determine what is the most + * efficient algorithm. + * + * @param graph1 + * @param graph2 + * @param vertexChecker may be null + * @param edgeChecker may be null + */ + public static GraphIsomorphismInspector createIsomorphismInspector( + Graph graph1, + Graph graph2, + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + int graphType = checkGraphsType(graph1, graph2); + return createAppropriateConcreteInspector( + graphType, + graph1, + graph2, + vertexChecker, + edgeChecker); + } + + /** + * Creates a new inspector, letting this class determine what is the most + * efficient algorithm and using default equivalence comparators. + * + *

    same as calling createIsomorphismInspector(graph1,graph2,null,null); + * + * @param graph1 + * @param graph2 + */ + public static GraphIsomorphismInspector createIsomorphismInspector( + Graph graph1, + Graph graph2) + { + return createIsomorphismInspector(graph1, graph2, null, null); + } + + /** + * Creates a new inspector for a particular graph type (planar / tree / + * other). + * + * @param type - AdaptiveIsomorphismInspectorFactory.GRAPH_TYPE_XXX + * @param graph1 + * @param graph2 + * @param vertexChecker - can be null + * @param edgeChecker - can be null + */ + public static GraphIsomorphismInspector + createIsomorphismInspectorByType( + int type, + Graph graph1, + Graph graph2, + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + return createAppropriateConcreteInspector( + type, + graph1, + graph2, + vertexChecker, + edgeChecker); + } + + /** + * Creates a new inspector for a particular graph type (planar / tree / + * other) using default equivalence comparators. + * + *

    same as calling + * createAppropriateConcreteInspector(graph1,graph2,null,null); + * + * @param type - AdaptiveIsomorphismInspectorFactory.GRAPH_TYPE_XXX + * @param graph1 + * @param graph2 + */ + public static GraphIsomorphismInspector + createIsomorphismInspectorByType( + int type, + Graph graph1, + Graph graph2) + { + return createAppropriateConcreteInspector( + type, + graph1, + graph2, + null, + null); + } + + /** + * Checks the graph type, and accordingly decides which type of concrete + * inspector class to create. This implementation creates an exhaustive + * inspector without further tests, because no other implementations are + * available yet. + * + * @param graph1 + * @param graph2 + * @param vertexChecker + * @param edgeChecker + */ + protected static GraphIsomorphismInspector + createAppropriateConcreteInspector( + int graphType, + Graph graph1, + Graph graph2, + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + assertUnsupportedGraphTypes(graph1); + assertUnsupportedGraphTypes(graph2); + GraphIsomorphismInspector currentInspector = null; + + switch (graphType) { + case GRAPH_TYPE_PLANAR: + case GRAPH_TYPE_TREE: + case GRAPH_TYPE_ARBITRARY: + currentInspector = + createTopologicalExhaustiveInspector( + graph1, + graph2, + vertexChecker, + edgeChecker); + break; + + default: + + throw new IllegalArgumentException( + "The type was not one of the supported types."); + } + return currentInspector; + } + + /** + * Checks if one of the graphs is from unsupported graph type and throws + * IllegalArgumentException if it is. The current unsupported types are + * graphs with multiple-edges. + * + * @param graph1 + * @param graph2 + * + * @throws IllegalArgumentException + */ + protected static void assertUnsupportedGraphTypes(Graph g) + throws IllegalArgumentException + { + if ((g instanceof Multigraph) + || (g instanceof DirectedMultigraph) + || (g instanceof Pseudograph)) + { + throw new IllegalArgumentException( + "graph type not supported for the graph" + g); + } + } + + protected static int checkGraphsType(Graph graph1, Graph graph2) + { + return GRAPH_TYPE_ARBITRARY; + } + + /** + * @return ExhaustiveInspector, where the equivalence comparator is chained + * with a topological comparator. This implementation uses: + *

  • vertex degree size comparator + */ + @SuppressWarnings("unchecked") + protected static GraphIsomorphismInspector + createTopologicalExhaustiveInspector( + Graph graph1, + Graph graph2, + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + VertexDegreeEquivalenceComparator degreeComparator = + new VertexDegreeEquivalenceComparator(); + EquivalenceComparatorChain> vertexChainedChecker = + new EquivalenceComparatorChainBase>( + degreeComparator); + vertexChainedChecker.appendComparator(vertexChecker); + + GraphIsomorphismInspector inspector = + + // FIXME hb060208 I don't understand how to generify this, yet + new EquivalenceIsomorphismInspector( + graph1, + graph2, + vertexChainedChecker, + edgeChecker); + return inspector; + } +} + +// End AdaptiveIsomorphismInspectorFactory.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java b/wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java new file mode 100644 index 0000000..9a23646 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java @@ -0,0 +1,325 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * EquivalenceIsomorphismInspector.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: EquivalenceIsomorphismInspector.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.experimental.equivalence.*; +import org.jgrapht.experimental.permutation.*; + + +/** + * The current implementation uses the vertexComparator to greatly increase the + * test speed by dividing the vertexes into equivalent groups and permuting + * inside them only. The EdgeComparator is used to test edges, but not to make a + * finer division, thus it adds overhead. Use it only when needed. + * + * @author Assaf + * @since Jul 29, 2005 + */ +class EquivalenceIsomorphismInspector + extends AbstractExhaustiveIsomorphismInspector +{ + //~ Constructors ----------------------------------------------------------- + + /** + * @param graph1 + * @param graph2 + * @param vertexChecker eq. group checker for vertexes. If null, + * UniformEquivalenceComparator will be used as default (always return true) + * @param edgeChecker eq. group checker for edges. If null, + * UniformEquivalenceComparator will be used as default (always return true) + */ + public EquivalenceIsomorphismInspector( + Graph graph1, + Graph graph2, + + // XXX hb 060128: FOllowing parameter may need Graph + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + super(graph1, graph2, vertexChecker, edgeChecker); + } + + /** + * Constructor which uses the default comparators. + * + * @see ExhaustiveIsomorphismInspector(Graph,Graph,EquivalenceComparator,EquivalenceComparator) + */ + public EquivalenceIsomorphismInspector( + Graph graph1, + Graph graph2) + { + super(graph1, graph2); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Creates the permutation iterator according to equivalance class. + * + *

    1. Get the eq.group (ordered by size) array of the source vertex set + * (vertexSet1) + * + *

    2. Get the eq.group ordered array of vertexSet2. + * + *

    3. Reorder the second array to match the group order of the first + * array sets. 4. Use CompoundPermutationIter (and not regular + * IntegerPermutationIter) to permute only inside groups. + * + *

    + *

    That's it. If the eq.group comaparator is strong enough to provide + * small groups, this algortihm will produce a small possible permutations + * numbers. example: G1: [A,B,F,X,Y] [A->B,B->X,X->Y] + * + *

    G2: [D,Z,C,U,F] [D->C,Z->C,U->Z] + * + *

    vertexEq: three groups , one all letters A-E , second all letters S-Z + * , third the letter 'f'. 1. [(f)size=1, (X,Y)size=2 , (A,B)size=2] 2. + * [(f)size=1 ,(C,D)size=2 , (Z,U)size=2] 3. the match is done by reordering + * the second array to have the equiviavlant order :##[(f)size=1 , + * (Z,U)size=2 , (C,D)size=2]## 4.for example G2 will not do all 5!=120 + * permutations , but 2!x2!x1!=4 permutations only which are: (of the 3rd + * array) [ F, Z , U , C , D ] [ F, Z , U , D , C ] [ F, U , Z, C , D ] [ F, + * U , Z , D , C ] + * + * @return null, if the eq.group do not match (there cannot be any + * permutation for eq.groups) or the sets do not match in size; otherwise, + * the permutationiterator otherwise + * + * @see AbstractExhaustiveIsomorphismInspector#createPermutationIterator(Set, + * Set) + */ + @SuppressWarnings("unchecked") + protected CollectionPermutationIter createPermutationIterator( + Set vertexSet1, + Set vertexSet2) + { + if (vertexSet1.size() != vertexSet2.size()) { + // throw new IllegalArgumentException("the two vertx-sets + // parameters must be of" + // +"the same size. The first size was:"+vertexSet1.size() + // +" the other size was:" +vertexSet2.size() ); + return null; // only instead of exception + } + + // 1// + EquivalenceSet [] eqGroupArray1 = + EquivalenceSetCreator.createEqualityGroupOrderedArray( + vertexSet1, + this.vertexComparator, + this.graph1); + + // 2// + EquivalenceSet [] eqGroupArray2 = + EquivalenceSetCreator.createEqualityGroupOrderedArray( + vertexSet2, + this.vertexComparator, + this.graph2); + + // 3// + boolean reorderSuccess = + reorderTargetArrayToMatchSourceOrder(eqGroupArray1, eqGroupArray2); // 2 is the target + if (!reorderSuccess) { + // if reordering fail , no match can be done + return null; + } + + // reorder set1 (source), so when we work with the flat array of the + // second array, + // the permutations will be relevant. + // note that it does not start in any way related to eqGroup sizes. + + V [] reorderingVertexSet1Temp = (V []) new Object[vertexSet1.size()]; + fillElementsflatArray(eqGroupArray1, reorderingVertexSet1Temp); + vertexSet1.clear(); + vertexSet1.addAll(Arrays.asList(reorderingVertexSet1Temp)); + + // 4//use CompoundPermutationIter to permute only inside groups. + // the CollectionPermutationIter needs a array/set of objects and a + // permuter which will + // work on that set/array order. lets make these two: + // 1. create array of the vertexes , by flattening the eq.group array + // contents + + V [] flatVertexArray = (V []) new Object[vertexSet2.size()]; + fillElementsflatArray(eqGroupArray2, flatVertexArray); + + // 2. make the permuter according to the groups size + int [] groupSizesArray = new int[eqGroupArray1.length]; + + // iterate over the EqualityGroup array + for ( + int eqGroupCounter = 0; + eqGroupCounter < eqGroupArray2.length; + eqGroupCounter++) + { + // now for (.2.) size count + groupSizesArray[eqGroupCounter] = + eqGroupArray2[eqGroupCounter].size(); + } + + ArrayPermutationsIter arrayPermIter = + PermutationFactory.createByGroups(groupSizesArray); + CollectionPermutationIter vertexPermIter = + new CollectionPermutationIter( + Arrays.asList(flatVertexArray), + arrayPermIter); + + return vertexPermIter; + } + + /** + * Reorders inplace targetArray + * + *

    rules: + *

  • try to match only group of the same size and then hashcode + *
  • it is enough to choose one from each group to see if a match exist. + * + *

    Algorithm: hold counters in the two arrays. [a,b,c,d,e] assume groups + * are:a,(b,c,d),e [a,c,d,b,e] c1=0 , c2=0 check if eqvivalent . if not , + * advance , as long as both size and hashcode are the same. if found a + * match , swap the group positions in array2. if not , throws + * IllegalArgumentExcpetion. Assumption: array size is the same. not + * checked. + * + * @param sourceArray + * @param targetArray + * + * @return true if the array was reordered successfully. false if not(It + * will happen if there is no complete match between the groups) + */ + private boolean reorderTargetArrayToMatchSourceOrder( + EquivalenceSet [] sourceArray, + EquivalenceSet [] targetArray) + { + boolean result = true; + for ( + int sourceIndex = 0; + sourceIndex < sourceArray.length; + sourceIndex++) + { + int currTargetIndex = sourceIndex; + + // if they are already equivalent do nothing. + EquivalenceSet sourceEqGroup = sourceArray[sourceIndex]; + EquivalenceSet targetEqGroup = targetArray[currTargetIndex]; + if (!sourceEqGroup.equals(targetEqGroup)) { + // iterate through the next group in the targetArray until + // a new size or hashcode is seen + boolean foundMatch = false; + int sourceSize = sourceEqGroup.size(); + int sourceHashCode = sourceEqGroup.hashCode(); + while ( + (targetEqGroup.size() == sourceSize) + && (targetEqGroup.hashCode() == sourceHashCode) + && (currTargetIndex < (targetArray.length - 1))) + { + currTargetIndex++; + targetEqGroup = targetArray[currTargetIndex]; + if (targetEqGroup.equals(sourceEqGroup)) { + foundMatch = true; + + // swap . targetEqGroup will serve as the temp + // variable. + targetArray[currTargetIndex] = targetArray[sourceIndex]; + targetArray[sourceIndex] = targetEqGroup; + } + } + if (!foundMatch) { + // a match was not found + // throw new IllegalArgumentException("could not reorder + // the array , because the groups don`t match"); + result = false; + break; + } + } + } + return result; + } + + /** + * @param eqGroupArray + * @param flatArray an empy array with the proper size + */ + protected void fillElementsflatArray( + EquivalenceSet [] eqGroupArray, + Object [] flatVertexArray) + { + int flatVertexArrayNextFree = 0; // the next free place in the array + + // iterate over the EqualityGroup array + for ( + int eqGroupCounter = 0; + eqGroupCounter < eqGroupArray.length; + eqGroupCounter++) + { + Object [] currGroupArray = eqGroupArray[eqGroupCounter].toArray(); + + // copy this small array to the free place in the big + // flatVertexArray + System.arraycopy( + currGroupArray, // src + 0, // srcPos + flatVertexArray, // dest + flatVertexArrayNextFree, // destPos + currGroupArray.length // length + ); + flatVertexArrayNextFree += currGroupArray.length; + } + } + + /** + * We know for sure, that the sets are alreay checked for equivalence , so + * it will return true without any further checks. + * + * @see AbstractExhaustiveIsomorphismInspector#areVertexSetsOfTheSameEqualityGroup( + * Set, Set) + */ + protected boolean areVertexSetsOfTheSameEqualityGroup( + Set vertexSet1, + Set vertexSet2) + { + return true; + } +} + +// End EquivalenceIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java b/wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java new file mode 100644 index 0000000..36afff3 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java @@ -0,0 +1,95 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * GraphIsomorphismInspector.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + + +/** + * Isomorphism Overview + * + *

    Isomorphism is the problem of testing whether two graphs are topologically + * the same. Suppose we are given a collection of graphs and must perform some + * operation on each of them. If we can identify which of the graphs are + * duplicates, they can be discarded so as to avoid redundant work. + * + *

    In Formal Math: Input description: Two graphs, G and H. Problem + * description: Find a (or all) mappings f of the vertices of G to the + * vertices of H such that G and H are identical; i.e. (x,y) is an edge of G iff + * (f(x),f(y)) is an edge of H. + * http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK4/NODE180.HTM. + * + *

    Efficiency: The general algorithm is not polynomial, however + * polynomial algorithms are known for special cases, like acyclic graphs, + * planar graphs etc. There are several heuristic algorithms which gives quite + * good results (polynomial) in general graphs, for most but not all cases. + * + *

    Usage: + * + *

      + *
    1. Choose comparators for the vertexes and edges. You may use the default + * comparator by sending null parameters for them to the constructor. Example: + * Assume Your graphs are of human relations. Each vertex is either a man or a + * woman and also has the person name. You may decide that isomorphism is + * checked according to gender, but not according to the specific name. So you + * will create a comparator that distinguishes vertexes only according to + * gender. + *
    2. Use the isIsomorphic() method as a boolean test for isomorphism + *
    3. Use the Iterator interface to iterate through all the possible + * isomorphism ordering. + *
    + * + * @author Assaf Lehr + * @since Jul 15, 2005 + */ +// REVIEW jvs 5-Sept-2005: Since we're using JDK1.5 now, we should be +// able to declare this as Iterator, correct? Otherwise +// the caller doesn't even know what they're getting back. +public interface GraphIsomorphismInspector + extends Iterator +{ + //~ Methods ---------------------------------------------------------------- + + /** + * @return true iff the two graphs are isomorphic + */ + public boolean isIsomorphic(); +} + +// End GraphIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java b/wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java new file mode 100644 index 0000000..5aa3333 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java @@ -0,0 +1,232 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * GraphOrdering.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Holds graph information as int labels only. vertexes: 1,2,3,4 edges:1->2 , + * 3->4 ,1->1. Implementation as imutable graph by int[] for vetexes and + * LabelsEdge[] for edges. The current algorithms do not support graph with + * multiple edges (Multigraph / Pseudograph). For the maintaner: The reason for + * it is the use of edges sets of LabelsEdge in which the equals checks for + * source and target vertexes. Thus there cannot be two LabelsEdge with the same + * source and target in the same Set. + * + * @author Assaf + * @since May 20, 2005 + */ +public class GraphOrdering +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Holds a mapping between key=V(vertex) and value=Integer(vertex order). It + * can be used for identifying the order of regular vertex/edge. + */ + private Map mapVertexToOrder; + + /** + * Holds a HashSet of all LabelsGraph of the graph. + */ + private Set labelsEdgesSet; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new labels graph according to the regular graph. After its + * creation they will no longer be linked, thus changes to one will not + * affect the other. + * + * @param regularGraph + */ + public GraphOrdering(Graph regularGraph) + { + this(regularGraph, regularGraph.vertexSet(), regularGraph.edgeSet()); + } + + /** + * Creates a new labels graph according to the regular graph. After its + * creation they will no longer be linked, thus changes to one will not + * affect the other. + * + * @param regularGraph + * @param vertexSet + * @param edgeSet + */ + public GraphOrdering( + Graph regularGraph, + Set vertexSet, + Set edgeSet) + { + init(regularGraph, vertexSet, edgeSet); + } + + //~ Methods ---------------------------------------------------------------- + + private void init(Graph g, Set vertexSet, Set edgeSet) + { + // create a map between vertex value to its order(1st,2nd,etc) + // "CAT"=1 "DOG"=2 "RHINO"=3 + + this.mapVertexToOrder = new HashMap(vertexSet.size()); + + int counter = 0; + for (V vertex : vertexSet) { + mapVertexToOrder.put(vertex, new Integer(counter)); + counter++; + } + + // create a friendlier representation of an edge + // by order, like 2nd->3rd instead of B->A + // use the map to convert vertex to order + // on directed graph, edge A->B must be (A,B) + // on undirected graph, edge A-B can be (A,B) or (B,A) + + this.labelsEdgesSet = new HashSet(edgeSet.size()); + for (E edge : edgeSet) { + V sourceVertex = g.getEdgeSource(edge); + Integer sourceOrder = mapVertexToOrder.get(sourceVertex); + int sourceLabel = sourceOrder.intValue(); + int targetLabel = + (mapVertexToOrder.get(g.getEdgeTarget(edge))).intValue(); + + LabelsEdge lablesEdge = new LabelsEdge(sourceLabel, targetLabel); + this.labelsEdgesSet.add(lablesEdge); + + if (g instanceof UndirectedGraph) { + LabelsEdge oppositeEdge = + new LabelsEdge(targetLabel, sourceLabel); + this.labelsEdgesSet.add(oppositeEdge); + } + } + } + + /** + * Tests equality by order of edges + */ + public boolean equalsByEdgeOrder(GraphOrdering otherGraph) + { + boolean result = + this.getLabelsEdgesSet().equals(otherGraph.getLabelsEdgesSet()); + + return result; + } + + public Set getLabelsEdgesSet() + { + return labelsEdgesSet; + } + + /** + * This is the format example: + * + *
    +       mapVertexToOrder=        labelsOrder=
    +     * 
    + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("mapVertexToOrder="); + + // vertex will be printed in their order + Object [] vertexArray = new Object[this.mapVertexToOrder.size()]; + Set keySet = this.mapVertexToOrder.keySet(); + for (V currVertex : keySet) { + Integer index = this.mapVertexToOrder.get(currVertex); + vertexArray[index.intValue()] = currVertex; + } + sb.append(Arrays.toString(vertexArray)); + sb.append("labelsOrder=").append(this.labelsEdgesSet.toString()); + return sb.toString(); + } + + //~ Inner Classes ---------------------------------------------------------- + + private class LabelsEdge + { + private int source; + private int target; + private int hashCode; + + public LabelsEdge(int aSource, int aTarget) + { + this.source = aSource; + this.target = aTarget; + this.hashCode = + new String(this.source + "" + this.target).hashCode(); + } + + /** + * Checks both source and target. Does not check class type to be fast, + * so it may throw ClassCastException. Careful! + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) + { + LabelsEdge otherEdge = (LabelsEdge) obj; + if ((this.source == otherEdge.source) + && (this.target == otherEdge.target)) + { + return true; + } else { + return false; + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() + { + return this.hashCode; // filled on constructor + } + + public String toString() + { + return this.source + "->" + this.target; + } + } +} + +// End GraphOrdering.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java b/wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java new file mode 100644 index 0000000..1d5fb29 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java @@ -0,0 +1,151 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * IsomorphismRelation.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + * Holds an isomorphism relation for two graphs. It contains a mapping between + * the two graphs. + * + *

    Usage: + * + *

      + *
    1. use getVertexCorrespondence() or + * getEdgeCorrespondence() to get the mapped object in the other graph. + *
    + * + *

    + *

    It consists of two vertexes array , the i-th vertex in the 1st array is + * the isomorphic eqv. of the i-th in 2nd array. Note that the getters are + * unsafe (they return the array and not a copy of it). + * + * @author Assaf + * @since May 27, 2005 + */ +public class IsomorphismRelation + implements GraphMapping +{ + //~ Instance fields -------------------------------------------------------- + + private List vertexList1; + private List vertexList2; + + private GraphMapping graphMapping = null; + + private Graph graph1; + private Graph graph2; + + //~ Constructors ----------------------------------------------------------- + + /** + */ + public IsomorphismRelation( + List aGraph1vertexArray, + List aGraph2vertexArray, + Graph g1, + Graph g2) + { + this.vertexList1 = aGraph1vertexArray; + this.vertexList2 = aGraph2vertexArray; + this.graph1 = g1; + this.graph2 = g2; + } + + //~ Methods ---------------------------------------------------------------- + + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("vertexList1: ").append( + this.vertexList1.toString()); + sb.append("\tvertexList2: ").append( + this.vertexList2.toString()); + return sb.toString(); + } + + public V getVertexCorrespondence(V vertex, boolean forward) + { + // lazy initializer for graphMapping + if (graphMapping == null) { + initGraphMapping(); + } + + return graphMapping.getVertexCorrespondence(vertex, forward); + } + + public E getEdgeCorrespondence(E edge, boolean forward) + { + // lazy initializer for graphMapping + if (graphMapping == null) { + initGraphMapping(); + } + + return graphMapping.getEdgeCorrespondence(edge, forward); + } + + /** + * We currently have the vertexes array. From them we will construct two + * maps: g1ToG2 and g2ToG1, using the array elements with the same index. + */ + private void initGraphMapping() + { + int mapSize = vertexList1.size(); + Map g1ToG2 = new HashMap(mapSize); + Map g2ToG1 = new HashMap(mapSize); + + for (int i = 0; i < mapSize; i++) { + V source = this.vertexList1.get(i); + V target = this.vertexList2.get(i); + g1ToG2.put(source, target); + g2ToG1.put(target, source); + } + this.graphMapping = + new DefaultGraphMapping( + g1ToG2, + g2ToG1, + this.graph1, + this.graph2); + } +} + +// End IsomorphismRelation.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java b/wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java new file mode 100644 index 0000000..c8ad67d --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java @@ -0,0 +1,148 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * PermutationIsomorphismInspector.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: PermutationIsomorphismInspector.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.experimental.equivalence.*; +import org.jgrapht.experimental.permutation.*; + + +/** + * Checks every possible permutation. + * + *

    It does not uses the graph topology to enhance the performance. It is + * recommended to use only if there cannot be a useful division into equivalence + * sets. + * + * @author Assaf + * @since Jul 29, 2005 + */ +class PermutationIsomorphismInspector + extends AbstractExhaustiveIsomorphismInspector +{ + //~ Constructors ----------------------------------------------------------- + + /** + * @param graph1 + * @param graph2 + * @param vertexChecker eq. group checker for vertexes. If null, + * UniformEquivalenceComparator will be used as default (always return true) + * @param edgeChecker eq. group checker for edges. If null, + * UniformEquivalenceComparator will be used as default (always return true) + */ + public PermutationIsomorphismInspector( + Graph graph1, + Graph graph2, + + // XXX hb 060128: FOllowing parameter may need Graph + EquivalenceComparator> vertexChecker, + EquivalenceComparator> edgeChecker) + { + super(graph1, graph2, vertexChecker, edgeChecker); + } + + /** + * Constructor which uses the default comparators. + * + * @see AbstractExhaustiveIsomorphismInspector#AbstractExhaustiveIsomorphismInspector(Graph, + * Graph) + */ + public PermutationIsomorphismInspector( + Graph graph1, + Graph graph2) + { + super(graph1, graph2); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Creates the permutation iterator, not dependant on equality group, or the + * other vertexset. + * + * @param vertexSet1 FIXME Document me + * @param vertexSet2 FIXME Document me + * + * @return the permutation iterator + */ + protected CollectionPermutationIter createPermutationIterator( + Set vertexSet1, + Set vertexSet2) + { + return new CollectionPermutationIter(vertexSet2); + } + + /** + * FIXME Document me FIXME Document me + * + * @param vertexSet1 FIXME Document me + * @param vertexSet2 FIXME Document me + * + * @return FIXME Document me + */ + protected boolean areVertexSetsOfTheSameEqualityGroup( + Set vertexSet1, + Set vertexSet2) + { + if (vertexSet1.size() != vertexSet2.size()) { + return false; + } + Iterator iter2 = vertexSet2.iterator(); + + // only check hasNext() of one , cause they are of the same size + for (Iterator iter1 = vertexSet1.iterator(); iter1.hasNext();) { + V vertex1 = iter1.next(); + V vertex2 = iter2.next(); + if (!this.vertexComparator.equivalenceCompare( + vertex1, + vertex2, + this.graph1, + this.graph2)) + { + return false; + } + } + return true; + } +} + +// End PermutationIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java b/wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java new file mode 100644 index 0000000..7275a53 --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java @@ -0,0 +1,178 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * VertexDegreeEquivalenceComparator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id: VertexDegreeEquivalenceComparator.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.isomorphism; + +import org.jgrapht.*; +import org.jgrapht.experimental.equivalence.*; + + +/** + * Two vertexes are equivalent under this comparator if and only if: + * + *

      + *
    1. they have the same IN degree + * + *

      AND + *

    2. they have the same OUT degree + *
    + * + * @author Assaf + * @since Jul 21, 2005 + */ +public class VertexDegreeEquivalenceComparator + implements EquivalenceComparator> +{ + //~ Constructors ----------------------------------------------------------- + + /** + */ + public VertexDegreeEquivalenceComparator() + { + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Compares the in degrees and the out degrees of the two vertexes. + * + *

    One may reside in an Undirected Graph and the other in a Directed + * graph, or both on the same graph type. + * + * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, + * Object) + */ + public boolean equivalenceCompare( + V vertex1, + V vertex2, + Graph context1, + Graph context2) + { + // note that VertexDegreeComparator cannot be used. It supports only + // directed graphs. + InOutDegrees inOut1 = getInOutDegrees(context1, vertex1); + InOutDegrees inOut2 = getInOutDegrees(context2, vertex2); + boolean result = inOut1.equals(inOut2); + return result; + } + + /** + * Hashes using the in & out degree of a vertex + * + * @see EquivalenceComparator#equivalenceHashcode(Object, Object) + */ + public int equivalenceHashcode(V vertex, Graph context) + { + InOutDegrees inOut = getInOutDegrees(context, vertex); + + // hash it using the string hash. use the format N '-' N + StringBuffer sb = new StringBuffer(); + sb.append(String.valueOf(inOut.inDegree)); + sb.append("-"); // to diffrentiate inner and outer + sb.append(String.valueOf(inOut.outDegree)); + return sb.toString().hashCode(); + } + + /** + * Calculates the In and Out degrees of vertexes. Supported graph types: + * UnDirectedGraph, DirectedGraph. In UnDirected graph, the in = out (as if + * it was undirected and every edge is both an in and out edge) + * + * @param aContextGraph + * @param vertex + */ + protected InOutDegrees getInOutDegrees(Graph aContextGraph, + V vertex) + { + int inVertexDegree = 0; + int outVertexDegree = 0; + if (aContextGraph instanceof UndirectedGraph) { + UndirectedGraph undirectedGraph = + (UndirectedGraph) aContextGraph; + inVertexDegree = undirectedGraph.degreeOf(vertex); + outVertexDegree = inVertexDegree; // it is UNdirected + } else if (aContextGraph instanceof DirectedGraph) { + DirectedGraph directedGraph = + (DirectedGraph) aContextGraph; + inVertexDegree = directedGraph.inDegreeOf(vertex); + outVertexDegree = directedGraph.outDegreeOf(vertex); + } else { + throw new RuntimeException( + "contextGraph is of unsupported type . It must be one of these two :" + + " UndirectedGraph or DirectedGraph"); + } + return new InOutDegrees(inVertexDegree, outVertexDegree); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Simple structure used to hold the two ints: vertex in degree and vertex + * out degree. Useful as returned value for methods which calculate both at + * the same time. + * + * @author Assaf + * @since Jul 21, 2005 + */ + protected class InOutDegrees + { + public int inDegree; + public int outDegree; + + public InOutDegrees(int aInDegree, int aOutDegree) + { + this.inDegree = aInDegree; + this.outDegree = aOutDegree; + } + + /** + * Checks both inDegree and outDegree. Does not check class type to save + * time. If should be used with caution. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) + { + InOutDegrees other = (InOutDegrees) obj; + return ((this.inDegree == other.inDegree) + && (this.outDegree == other.outDegree)); + } + } +} + +// End VertexDegreeEquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/package.html b/wdl/org/jgrapht/experimental/isomorphism/package.html new file mode 100644 index 0000000..07c613f --- /dev/null +++ b/wdl/org/jgrapht/experimental/isomorphism/package.html @@ -0,0 +1,6 @@ + + + +Algorithms which provide isomorphism check between two graphs. + + diff --git a/wdl/org/jgrapht/experimental/package.html b/wdl/org/jgrapht/experimental/package.html new file mode 100644 index 0000000..2a72e67 --- /dev/null +++ b/wdl/org/jgrapht/experimental/package.html @@ -0,0 +1,11 @@ + + + +

    A package that contains experimental work or work-in-progress that +is not yet ready to be included in a release. It may contain classes +that are: incomplete, not yet documented, have not yet reached a +satisfying form, etc.

    + +

    The only requirement for classes included here is to compile.

    + + \ No newline at end of file diff --git a/wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java b/wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java new file mode 100644 index 0000000..6d350bb --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java @@ -0,0 +1,56 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * ArrayPermutationsIter.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.permutation; + +/** + * An interface to iterate over array permutations. Similiar to Iterator, but + * with specific return types and without the remove() method. + * + * @author Assaf + * @since Jul 29, 2005 + */ +public interface ArrayPermutationsIter +{ + //~ Methods ---------------------------------------------------------------- + + public int [] nextPermutation(); + + public boolean hasNextPermutaions(); +} + +// End ArrayPermutationsIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java b/wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java new file mode 100644 index 0000000..11e8071 --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java @@ -0,0 +1,185 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * CollectionPermutationIter.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.permutation; + +import java.util.*; + + +/** + * Given a container with elements (Collection,Enumeration,array) defines a + * permutation iterator which returns, on each iteration, a differnt permutation + * of the source container. You may choose a different container + * type(Collection/Array/etc) for each next call. It will continue as if they + * were the same iterator. + * + * @author Assaf + * @since May 20, 2005 + */ +public class CollectionPermutationIter +{ + //~ Instance fields -------------------------------------------------------- + + private ArrayPermutationsIter permOrder; + private List sourceArray; + + /** + * change everry calculation.can be retrieved publicly + */ + private int [] currPermutationArray; + + //~ Constructors ----------------------------------------------------------- + + /** + * Note: the Set interface does not guarantee iteration order. This method + * iterates on the set to get the initial order and after that the data will + * be saved internally in another (ordered) container. So, remeber that the + * Initial order can be different from the objectSet.toString() method. If + * you want it to be the same, use a LinkedHashSet , or use the array + * constructor. + * + * @param objectsSet + */ + public CollectionPermutationIter(Set objectsSet) + { + this( + new ArrayList(objectsSet), + new IntegerPermutationIter(objectsSet.size())); + } + + /** + * Uses a permArray like [1,1,1,2] where some of the permutations are not + * relevant. Here there will be 4 permutations (only the '2' position is + * important) + * + * @param objectsArray + * @param permuter + */ + public CollectionPermutationIter(List objectsArray) + { + this( + objectsArray, + new IntegerPermutationIter(objectsArray.size())); + } + + public CollectionPermutationIter( + List objectsArray, + ArrayPermutationsIter permuter) + { + this.permOrder = permuter; + this.sourceArray = objectsArray; + } + + //~ Methods ---------------------------------------------------------------- + + public boolean hasNext() + { + return this.permOrder.hasNextPermutaions(); + } + + /** + * On first call, returns the source as an array; on any other call + * thereafter, a new permutation + * + * @return null if we overflowed! the array otherwise + */ + public List getNextArray() + { + List permutationResult; // will hold the array result + if (this.permOrder.hasNextPermutaions()) { + this.currPermutationArray = this.permOrder.nextPermutation(); + permutationResult = applyPermutation(); + } else { + permutationResult = null; + } + + return permutationResult; + } + + private List applyPermutation() + { + ArrayList output = new ArrayList(sourceArray); + + // Example : this.sourceArray = ["A","B","C","D"] + // perOrder: = [ 1 , 0 , 3 , 2 ] + // result : = ["B","A","D","C"] + for (int i = 0; i < output.size(); i++) { + output.set( + i, + this.sourceArray.get(this.currPermutationArray[i])); + } + return output; + } + + /** + * Wrap result to a Set. + * + * @return null if we overflowed! the set otherwise + */ + public Set getNextSet() + { + List result = getNextArray(); + if (result == null) { + return null; + } else // wrap in a SET + { + Set resultSet = new LinkedHashSet(result); + return resultSet; + } + } + + public int [] getCurrentPermutationArray() + { + return this.currPermutationArray; + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("Permutation int[]="); + sb.append(Arrays.toString(getCurrentPermutationArray())); + + List permutationResult = applyPermutation(); + sb.append("\nPermutationSet Source Object[]="); + sb.append(this.sourceArray.toString()); + sb.append("\nPermutationSet Result Object[]="); + sb.append(permutationResult.toString()); + return sb.toString(); + } +} + +// End CollectionPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java b/wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java new file mode 100644 index 0000000..c988698 --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java @@ -0,0 +1,307 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * CompoundPermutationIter.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.permutation; + +import java.util.*; + +import org.jgrapht.util.*; + + +/** + * For permutation like this: + *
  • 1,2 are the same eq.group (numbers) + *
  • a,b are og the same eq.group (letters) + *
  • '$' is of its own eq. group (signs) Let the order of the group be + * (arbitrary): signs,numbers,letters (note that for performance reasons, this + * arbitrary order is the worst! see Performance section below) + * + *

    These are the possible compound perm: [$,1,2,a,b,c] + * + *

    [$,1,2,a,c,b] + * + *

    [$,1,2,b,a,c] + * + *

    [$,1,2,b,c,a] + * + *

    [$,1,2,c,a,b] + * + *

    [$,1,2,c,b,a] + * + *

    [$,2,1,a,b,c] + * + *

    [$,2,1,a,c,b] + * + *

    [$,2,1,b,a,c] + * + *

    [$,2,1,b,c,a] + * + *

    [$,2,1,c,a,b] + * + *

    [$,2,1,c,b,a] + * + *

    The overall number is the product of the factorials of each eq. group + * size; in our example : (1!)x(2!)x(3!)=1x2x6=12. Using the constructor with + * eq.group sizes and initial order [1,2,3], the result permutations are + * retrieved as numbers in an array, where [0,1,2,3,4,5] means [$,1,2,a,b,c]: + * + *

    [0,1,2,3,5,4] + * + *

    [0,1,2,4,3,5] + * + *

    etc. etc., till: + * + *

    [0,2,1,5,4,3] means [$,2,1,c,b,a] + * + *

    + *

    Performance: The implementation tries to advance each time the + * group zero, if it does not succeed, it tries the next group (1,2 and so on), + * so: try to put the largest group as the first groups, UNLIKE the example. + * Performance-wise it is better to do [a,b,c,1,2,$] .The effect is improvement + * by constant (for example, by 2) + * + * @author Assaf + * @since May 30, 2005 + */ +public class CompoundPermutationIter + implements ArrayPermutationsIter, + Iterator +{ + //~ Instance fields -------------------------------------------------------- + + IntegerPermutationIter [] permArray; + + /** + * on the example 1+2+3=6 + */ + private int totalPermArraySize; + + /** + * The overall number is the product of the factorial of each eq. group + * size. + */ + private int max; + + private int iterCounter = 0; + + //~ Constructors ----------------------------------------------------------- + + /** + * For the class example, use [1,2,2]. order matters! (performance-wise too) + * + * @param equalityGroupsSizesArray + */ + public CompoundPermutationIter(int [] equalityGroupsSizesArray) + { + init(equalityGroupsSizesArray); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Creates an IntegerPermutationIter class per equalityGroup with different + * integers. + * + * @param equalityGroupsSizesArray + */ + private void init(int [] equalityGroupsSizesArray) + { + this.permArray = + new IntegerPermutationIter[equalityGroupsSizesArray.length]; + + int counter = 0; + this.max = 1; // each time , multiply by factorail(eqGroupSize) + for ( + int eqGroup = 0; + eqGroup < equalityGroupsSizesArray.length; + eqGroup++) + { + // create an array of eq.group size filled with values + // of counter, counter+1, ... counter+size-1 + int currGroupSize = equalityGroupsSizesArray[eqGroup]; + int [] currArray = new int[currGroupSize]; + for (int i = 0; i < currGroupSize; i++) { + currArray[i] = counter; + counter++; + } + this.permArray[eqGroup] = new IntegerPermutationIter(currArray); + this.permArray[eqGroup].getNext(); // first iteration return the + // source + + // each time , multiply by factorail(eqGroupSize) + this.max *= MathUtil.factorial(currGroupSize); + } + this.totalPermArraySize = counter; + + // calc max + } + + public Object next() + { + return getNext(); + } + + /** + * Iteration may be one of these two: 1. the last group advances by one + * iter, all else stay. 2. the last group cannot advance , so it restarts + * but telling the group after it to advance (done recursively till some + * group can advance) + */ + public int [] getNext() + { + if (this.iterCounter == 0) { + // just return it , without change + this.iterCounter++; + return getPermAsArray(); + } + + int firstGroupCapableOfAdvancing = -1; + int currGroupIndex = 0; // + while (firstGroupCapableOfAdvancing == -1) { + IntegerPermutationIter currGroup = this.permArray[currGroupIndex]; + + if (currGroup.hasNext()) { + currGroup.getNext(); + + // restart all that we passed on + for (int i = 0; i < currGroupIndex; i++) { + restartPermutationGroup(i); + } + firstGroupCapableOfAdvancing = currGroupIndex; + } + + currGroupIndex++; + if (currGroupIndex >= this.permArray.length) { + break; + } + } + + this.iterCounter++; + + if (firstGroupCapableOfAdvancing == -1) { + // nothing found. we finished all iterations + return null; + } else { + int [] tempArray = getPermAsArray(); + return tempArray; + } + } + + /** + * Creates and returns a new array which consists of the eq. group current + * permutation arrays. For example, in the 10th iter ([$,2,1,b,c,a]) The + * permutations current statuses is [0] [2,1] [4,5,3] so retrieve + * [0,2,1,4,5,3] + */ + public int [] getPermAsArray() + { + int [] resultArray = new int[this.totalPermArraySize]; + int counter = 0; + for ( + int groupIndex = 0; + groupIndex < this.permArray.length; + groupIndex++) + { + int [] currPermArray = this.permArray[groupIndex].getCurrent(); + System.arraycopy( + currPermArray, + 0, + resultArray, + counter, + currPermArray.length); + counter += currPermArray.length; + } + return resultArray; + } + + /** + * Restarts by creating a new one instead. + * + * @param groupIndex + */ + private void restartPermutationGroup(int groupIndex) + { + int [] oldPermArray = this.permArray[groupIndex].getCurrent(); + Arrays.sort(oldPermArray); + this.permArray[groupIndex] = new IntegerPermutationIter(oldPermArray); + this.permArray[groupIndex].getNext(); + } + + public boolean hasNext() + { + boolean result; + if (this.iterCounter < this.max) { + result = true; + } else { + result = false; + } + return result; + } + + public int getMax() + { + return max; + } + + /* (non-Javadoc) + * @see ArrayPermutationsIter#nextPermutation() + */ + public int [] nextPermutation() + { + return (int []) next(); + } + + /* (non-Javadoc) + * @see ArrayPermutationsIter#hasNextPermutaions() + */ + public boolean hasNextPermutaions() + { + return hasNext(); + } + + /** + * UNIMPLEMENTED. always throws new UnsupportedOperationException + * + * @see java.util.Iterator#remove() + */ + public void remove() + { + throw new UnsupportedOperationException(); + } +} + +// End CompoundPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java b/wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java new file mode 100644 index 0000000..55fb14a --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java @@ -0,0 +1,311 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * IntegerPermutationIter.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.permutation; + +import java.util.*; + + +/** + * Iterates through permutations of N elements. + *

  • use getNext() to get the next permutation order, for example(N=4): + * perm0=[1,2,3,4] perm1=[1,2,4,3] perm2=[1,3,2,4] . + *
  • use hasNext() or verify by counter[1,1,1,2,3]; + * note that there are much less than 5! premutations here, because of the + * repetitive 1s. + * + * @param array creates a copy of it (so sort / later changes will not + * matter) + */ + public IntegerPermutationIter(int [] array) + { + int [] newArray = new int[array.length]; + System.arraycopy(array, 0, newArray, 0, array.length); + Arrays.sort(newArray); + init(newArray); + } + + //~ Methods ---------------------------------------------------------------- + + private void init(int [] array) + { + this.N = array.length; + this.Value = array; + this.currentValueBackup = this.Value; + permutationCounter = 0; + } + + /** + * Swaps by array indexes + * + * @param i + * @param j + */ + private void swap(int i, int j) + { + int temp = this.Value[i]; + this.Value[i] = this.Value[j]; + this.Value[j] = temp; + } + + private int [] arrayClone(int [] sourceArray) + { + int [] destArray = new int[sourceArray.length]; + System.arraycopy(sourceArray, 0, destArray, 0, sourceArray.length); + return destArray; + } + + private int [] getNextStartingWith2() + { + permutationCounter++; + int i = N - 1; + + if (i <= 0) // may happen only on N<=1 + + { + this.endWasReached = true; + return null; + } + + /** while (Value[i-1] >= Value[i]) + { + i = i-1; + }*/ + while (Value[i - 1] >= Value[i]) { + i = i - 1; + if (i == 0) { + this.endWasReached = true; + return null; + } + } + + int j = N; + + while (Value[j - 1] <= Value[i - 1]) { + j = j - 1; + } + + swap(i - 1, j - 1); // swap values at positions (i-1) and (j-1) + + i++; + j = N; + + while (i < j) { + swap(i - 1, j - 1); + i++; + j--; + } + return this.Value; + } + + /** + * Efficiency: O(N) implementation, try to take the next! + */ + public boolean hasNext() + { + if ((this.permutationCounter == 0) + || (this.wasNextValueCalculatedAlready)) + { + return true; + } else if (this.endWasReached) { + return false; + } + + boolean result = true; + // calculate the next value into this.value save the current result. in + // the end swap the arrays there is no way to know when to stop , but + // the out-of-bound + /* try + * { + * this.wasNextValueCalculatedAlready=true; + * getNextStartingWith2(); + * } + * catch (ArrayIndexOutOfBoundsException outOfBoundException) + * { + * endWasReached=true; + * result=false; + * }*/ + + getNextStartingWith2(); + this.wasNextValueCalculatedAlready = true; + if (endWasReached) { + return false; + } + + ////////////////////////////// + return result; + } + + public Object next() + { + return getNext(); + } + + /** + * Facade. use it with getNext. efficency: O(N) + * + * @return a new Array with the permutatation order. for example: + * perm0=[1,2,3,4] perm1=[1,2,4,3] perm2=[1,3,2,4] + */ + public int [] getNext() + { + if (!hasNext()) { + throw new RuntimeException( + "IntegerPermutationIter exceeds the total number of permutaions." + + " Suggestion: do a check with hasNext() , or count till getTotalNumberOfPermutations" + + " before using getNext()"); + } + + // if it is the first one , return original + int [] internalArray; + if (this.permutationCounter == 0) { + this.permutationCounter++; + internalArray = this.Value; + } else { + // if hasNext() has precaclulated it , take this value. + if (this.wasNextValueCalculatedAlready) { + internalArray = this.Value; + this.wasNextValueCalculatedAlready = false; + } else { + internalArray = getNextStartingWith2(); + if (this.endWasReached) { + return null; + } + } + } + this.currentValueBackup = arrayClone(internalArray); + return arrayClone(internalArray); + } + + public int [] getCurrent() + { + return arrayClone(this.currentValueBackup); + } + + /** + * Utility method to convert the array into a string examples: [] [0] + * [0,1][1,0] + * + * @param array + */ + public String toString(int [] array) + { + if (array.length <= 0) { + return "[]"; + } + StringBuffer stBuffer = new StringBuffer("["); + for (int i = 0; i < (array.length - 1); i++) { + stBuffer.append(array[i]).append(","); + } + stBuffer.append(array[array.length - 1]).append("]"); + return stBuffer.toString(); + } + + /** + * UNIMPLEMENTED. always throws new UnsupportedOperationException + * + * @see java.util.Iterator#remove() + */ + public void remove() + { + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see ArrayPermutationsIter#nextPermutation() + */ + public int [] nextPermutation() + { + return (int []) next(); + } + + /* (non-Javadoc) + * @see ArrayPermutationsIter#hasNextPermutaions() + */ + public boolean hasNextPermutaions() + { + return hasNext(); + } +} + +// End IntegerPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/PermutationFactory.java b/wdl/org/jgrapht/experimental/permutation/PermutationFactory.java new file mode 100644 index 0000000..540df61 --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/PermutationFactory.java @@ -0,0 +1,98 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * PermutationFactory.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.experimental.permutation; + +/** + * Factory to create Permutations of several types and use them as Enumerations. + * Note that callers may use them directly if they need to use special concrete + * methods. + * + *

    These types are: + * + *

    + *

  • All elements are different. There are N! possible permutations. + * + *

    example: source=[1,2,3] + * result=[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2][3,2,1] + * + *

    + *

  • Some of the elements are the same. + * + *

    example: source=[1,1,2] result=[1,1,2][1,2,1][2,1,1] + * + *

    + *

  • There are separate permutations groups, which are connected to one + * sequence. Permutations are allowed only inside the group. Possible sequences: + * product of factorial of each group. see example. + * + *

    example: assume source=the groups are sizes are : 1,2,2,5 elements + * will be created: (1),(2,3),(4,5). + * + *

    result=[1,(2,3),(4,5)] [1,(2,3),(5,4)] [1,(3,2),(5,4)] [1,(3,2),(4,5)]. In + * this example the number of possiblities is 1! x 2! x 2! = 4 + * + * @author Assaf Lehr + * @since Jun 3, 2005 + */ +public class PermutationFactory +{ + //~ Methods ---------------------------------------------------------------- + + public static ArrayPermutationsIter createRegular(int [] permSourceArray) + { + IntegerPermutationIter regularPerm = + new IntegerPermutationIter(permSourceArray); + return regularPerm; + } + + /** + * For efficiency, try putting the biggest groups at the beggining of the + * array. + * + * @param groupSizesArray . example [3,2] will create an array (0,1,2)(3,4) + */ + public static ArrayPermutationsIter createByGroups( + int [] groupSizesArray) + { + CompoundPermutationIter complexPerm = + new CompoundPermutationIter(groupSizesArray); + return complexPerm; + } +} + +// End PermutationFactory.java diff --git a/wdl/org/jgrapht/experimental/permutation/package.html b/wdl/org/jgrapht/experimental/permutation/package.html new file mode 100644 index 0000000..82cd61f --- /dev/null +++ b/wdl/org/jgrapht/experimental/permutation/package.html @@ -0,0 +1,6 @@ + + + +Classes to provide all the possible permutations of arrays or sets. + + diff --git a/wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java b/wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java new file mode 100644 index 0000000..857cf13 --- /dev/null +++ b/wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java @@ -0,0 +1,119 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * CompleteBipartiteGraphGenerator.java + * ------------------- + * (C) Copyright 2008-2008, by Andrew Newell and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 24-Dec-2008 : Initial revision (AN); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a complete + * bipartite graph of any size. This is a graph with two partitions; two + * vertices will contain an edge if and only if they belong to different + * partitions. + * + * @author Andrew Newell + * @since Dec 21, 2008 + */ +public class CompleteBipartiteGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int sizeA, sizeB; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new CompleteBipartiteGraphGenerator object. + * + * @param partitionOne This is the number of vertices in the first partition + * @param partitionTwo This is the number of vertices in the second parition + */ + public CompleteBipartiteGraphGenerator(int partitionOne, int partitionTwo) + { + if ((partitionOne < 0) || (partitionTwo < 0)) { + throw new IllegalArgumentException("must be non-negative"); + } + this.sizeA = partitionOne; + this.sizeB = partitionTwo; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Construct a complete bipartite graph + */ + public void generateGraph( + Graph target, + final VertexFactory vertexFactory, + Map resultMap) + { + if ((sizeA < 1) && (sizeB < 1)) { + return; + } + + //Create vertices in each of the partitions + Set a = new HashSet(); + Set b = new HashSet(); + for (int i = 0; i < sizeA; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + a.add(newVertex); + } + for (int i = 0; i < sizeB; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + b.add(newVertex); + } + + //Add an edge for each pair of vertices in different partitions + for (Iterator iterA = a.iterator(); iterA.hasNext();) { + V v = iterA.next(); + for (Iterator iterB = b.iterator(); iterB.hasNext();) { + target.addEdge(v, iterB.next()); + } + } + } +} + +// End CompleteBipartiteGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/CompleteGraphGenerator.java b/wdl/org/jgrapht/generate/CompleteGraphGenerator.java new file mode 100755 index 0000000..96e4cfe --- /dev/null +++ b/wdl/org/jgrapht/generate/CompleteGraphGenerator.java @@ -0,0 +1,139 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * CompleteGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by Tim Shearouse and Contributors. + * + * Original Author: Tim Shearouse + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 10-Feb-2008 : Initial revision (TS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a complete graph of any size. A complete graph is a graph where + * every vertex shares an edge with every other vertex. If it is a directed + * graph, then edges must always exist in both directions. On a side note, a + * complete graph is the least efficient possible graph in terms of memory and + * cpu usage. Note: This contructor was designed for a simple undirected or + * directed graph. It will act strangely when used with certain graph types, + * such as undirected multigraphs. Note, though, that a complete undirected + * multigraph is rather senseless -- you can keep adding edges and the graph is + * never truly complete. + * + * @author Tim Shearouse + * @since Nov 02, 2008 + */ +public class CompleteGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int size; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new CompleteGraphGenerator. + * + * @param size number of vertices to be generated + * + * @throws IllegalArgumentException if the specified size is negative. + */ + public CompleteGraphGenerator(int size) + { + if (size < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + this.size = size; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + if (size < 1) { + return; + } + + //Add all the vertices to the set + for (int i = 0; i < size; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + } + + /* + * We want two iterators over the vertex set, one fast and one slow. + * The slow one will move through the set once. For each vertex, + * the fast iterator moves through the set, adding an edge to all + * vertices we haven't connected to yet. + * + * If we have an undirected graph, the second addEdge call will return + * nothing; it will not add a second edge. + */ + Iterator slowI = target.vertexSet().iterator(); + Iterator fastI; + + while (slowI.hasNext()) { //While there are more vertices in the set + + V latestVertex = slowI.next(); + fastI = target.vertexSet().iterator(); + + //Jump to the first vertex *past* latestVertex + while (fastI.next() != latestVertex) { + ; + } + + //And, add edges to all remaining vertices + V temp; + while (fastI.hasNext()) { + temp = fastI.next(); + target.addEdge(latestVertex, temp); + target.addEdge(temp, latestVertex); + } + } + } +} + +// End CompleteGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/EmptyGraphGenerator.java b/wdl/org/jgrapht/generate/EmptyGraphGenerator.java new file mode 100644 index 0000000..21d6300 --- /dev/null +++ b/wdl/org/jgrapht/generate/EmptyGraphGenerator.java @@ -0,0 +1,95 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * EmptyGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates an empty + * graph of any size. An empty graph is a graph that has no edges. + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public class EmptyGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int size; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new EmptyGraphGenerator. + * + * @param size number of vertices to be generated + * + * @throws IllegalArgumentException if the specified size is negative. + */ + public EmptyGraphGenerator(int size) + { + if (size < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + this.size = size; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + for (int i = 0; i < size; ++i) { + target.addVertex(vertexFactory.createVertex()); + } + } +} + +// End EmptyGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/GraphGenerator.java b/wdl/org/jgrapht/generate/GraphGenerator.java new file mode 100644 index 0000000..105869f --- /dev/null +++ b/wdl/org/jgrapht/generate/GraphGenerator.java @@ -0,0 +1,80 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * GraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * GraphGenerator defines an interface for generating new graph structures. + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public interface GraphGenerator +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Generate a graph structure. The topology of the generated graph is + * dependent on the implementation. For graphs in which not all vertices + * share the same automorphism equivalence class, the generator may produce + * a labeling indicating the roles played by generated elements. This is the + * purpose of the resultMap parameter. For example, a generator for a wheel + * graph would designate a hub vertex. Role names used as keys in resultMap + * should be declared as public static final Strings by implementation + * classes. + * + * @param target receives the generated edges and vertices; if this is + * non-empty on entry, the result will be a disconnected graph since + * generated elements will not be connected to existing elements + * @param vertexFactory called to produce new vertices + * @param resultMap if non-null, receives implementation-specific mappings + * from String roles to graph elements (or collections of graph elements) + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap); +} + +// End GraphGenerator.java diff --git a/wdl/org/jgrapht/generate/GridGraphGenerator.java b/wdl/org/jgrapht/generate/GridGraphGenerator.java new file mode 100644 index 0000000..adb5659 --- /dev/null +++ b/wdl/org/jgrapht/generate/GridGraphGenerator.java @@ -0,0 +1,145 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2011, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * StarGraphGenerator.java + * ------------------- + * (C) Copyright 2011-2011, by Assaf Mizrachi and Contributors. + * + * Original Author: Assaf Mizrachi + * Contributor(s): - + * + * $Id: StarGraphGenerator.java 651 2008-12-24 21:13:41Z perfecthash $ + * + * Changes + * ------- + * 3-Jan-2011 : Initial revision (AM); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a bidirectional grid graph of any + * size. A grid graph is a two dimensional graph whose vertices correspond to + * the points in the plane with integer coordinates, x-coordinates being in the + * range 0,..., n, y-coordinates being in the range 1,...m, and two vertices are + * connected by an edge whenever the corresponding points are at distance 1. + * Vertices are created from left to right and from top to bottom. + * + * @author Assaf Mizrachi + * @since Dec 29, 2010 + */ +public class GridGraphGenerator + implements GraphGenerator +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Role for the vertices at the corners. + */ + public static final String CORNER_VERTEX = "Corner Vertex"; + + //~ Instance fields -------------------------------------------------------- + + private int rows; + + private int cols; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new GridGraphGenerator object with rows x cols dimension. + * + * @param rows the number of rows + * @param cols the number of columns + */ + public GridGraphGenerator(int rows, int cols) + { + if (rows < 2) { + throw new IllegalArgumentException( + "illegal number of rows (" + rows + + "). there must be at least two."); + } + if (cols < 2) { + throw new IllegalArgumentException( + "illegal number of columns (" + cols + + "). there must be at least two."); + } + this.rows = rows; + this.cols = cols; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + @Override public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + Map map = new TreeMap(); + + // Adding all vertices to the set + int cornerCtr = 0; + for (int i = 0; i < (rows * cols); i++) { + V vertex = vertexFactory.createVertex(); + target.addVertex(vertex); + map.put(i + 1, vertex); + + boolean isCorner = + (i == 0) || (i == (cols - 1)) || (i == (cols * (rows - 1))) + || (i == ((rows * cols) - 1)); + if (isCorner && (resultMap != null)) { + resultMap.put(CORNER_VERTEX + ' ' + ++cornerCtr, vertex); + } + } + + // Iterating twice over the key set, for undirected graph edges are + // added from upper vertices to lower, and from left to right. The + // second addEdge call will return nothing; it will not add a the edge + // at the opposite direction. For directed graph, edges in opposite + // direction are also added. + for (int i : map.keySet()) { + for (int j : map.keySet()) { + if ((((i % cols) > 0) + && ((i + 1) == Integer.valueOf(j))) + || ((i + cols) == j)) + { + target.addEdge(map.get(i), map.get(j)); + target.addEdge(map.get(j), map.get(i)); + } + } + } + } +} + +// End GridGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java b/wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java new file mode 100644 index 0000000..e58e714 --- /dev/null +++ b/wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java @@ -0,0 +1,118 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * HyperCubeGraphGenerator.java + * ------------------- + * (C) Copyright 2008-2008, by Andrew Newell and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 24-Dec-2008 : Initial revision (AN); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a hyper + * cube graph of any size. This is a graph that can be represented by bit + * strings, so for an n-dimensial hypercube each vertex resembles an n-length + * bit string. Then, two vertices are adjacent if and only if their bitstring + * differ by exactly one element. + * + * @author Andrew Newell + * @since Dec 21, 2008 + */ +public class HyperCubeGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int dim; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new HyperCubeGraphGenerator object. + * + * @param dim This is the dimension of the hypercube. + */ + public HyperCubeGraphGenerator(int dim) + { + this.dim = dim; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * This will generate the hypercube graph + */ + public void generateGraph( + Graph target, + final VertexFactory vertexFactory, + Map resultMap) + { + //Vertices are created, and they are included in the resultmap as their + //bitstring representation + int order = (int) Math.pow(2, dim); + LinkedList vertices = new LinkedList(); + for (int i = 0; i < order; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + vertices.add(newVertex); + if (resultMap != null) { + String s = Integer.toBinaryString(i); + while (s.length() < dim) { + s = "0" + s; + } + resultMap.put(s, newVertex); + } + } + + //Two vertices will have an edge if their bitstrings differ by exactly + //1 element + for (int i = 0; i < order; i++) { + for (int j = i + 1; j < order; j++) { + for (int z = 0; z < dim; z++) { + if ((j ^ i) == (1 << z)) { + target.addEdge(vertices.get(i), vertices.get(j)); + break; + } + } + } + } + } +} + +// End HyberCubeGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/LinearGraphGenerator.java b/wdl/org/jgrapht/generate/LinearGraphGenerator.java new file mode 100644 index 0000000..b0b676e --- /dev/null +++ b/wdl/org/jgrapht/generate/LinearGraphGenerator.java @@ -0,0 +1,124 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * LinearGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a linear graph of any size. For a directed graph, the edges are + * oriented from START_VERTEX to END_VERTEX. + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public class LinearGraphGenerator + implements GraphGenerator +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Role for the first vertex generated. + */ + public static final String START_VERTEX = "Start Vertex"; + + /** + * Role for the last vertex generated. + */ + public static final String END_VERTEX = "End Vertex"; + + //~ Instance fields -------------------------------------------------------- + + private int size; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new LinearGraphGenerator. + * + * @param size number of vertices to be generated + * + * @throws IllegalArgumentException if the specified size is negative. + */ + public LinearGraphGenerator(int size) + { + if (size < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + this.size = size; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + V lastVertex = null; + + for (int i = 0; i < size; ++i) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + + if (lastVertex == null) { + if (resultMap != null) { + resultMap.put(START_VERTEX, newVertex); + } + } else { + target.addEdge(lastVertex, newVertex); + } + + lastVertex = newVertex; + } + + if ((resultMap != null) && (lastVertex != null)) { + resultMap.put(END_VERTEX, lastVertex); + } + } +} + +// End LinearGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/RandomGraphGenerator.java b/wdl/org/jgrapht/generate/RandomGraphGenerator.java new file mode 100644 index 0000000..b55bf5a --- /dev/null +++ b/wdl/org/jgrapht/generate/RandomGraphGenerator.java @@ -0,0 +1,381 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * RandomGraphGenerator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + + +/** + * This Generator creates a random-topology graph of a specified number of + * vertexes and edges. An instance of this generator will always return the same + * graph-topology in calls to generateGraph(). The vertexes can be different + * (depends on the VertexFactory implementation) + * + *

    However, two instances which use the same constructor parameters will + * produce two different random graphs (note: as with any random generator, + * there is always a small possibility that two instances will create the same + * results). + * + * @author Assaf Lehr + * @since Aug 6, 2005 + */ +public class RandomGraphGenerator + implements GraphGenerator +{ + //~ Static fields/initializers --------------------------------------------- + + private static long seedUniquifier = 8682522807148012L; + + //~ Instance fields -------------------------------------------------------- + + protected int numOfVertexes; + protected int numOfEdges; + protected Random randomizer; + private long randomizerSeed; + + //~ Constructors ----------------------------------------------------------- + + public RandomGraphGenerator(int aNumOfVertexes, int aNumOfEdges) + { + if ((aNumOfVertexes < 0) || (aNumOfEdges < 0)) { + throw new IllegalArgumentException("must be non-negative"); + } + this.numOfVertexes = aNumOfVertexes; + this.numOfEdges = aNumOfEdges; + + this.randomizerSeed = chooseRandomSeedOnce(); + this.randomizer = new Random(this.randomizerSeed); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Should be called only once on creation. Chooses a seed which can be used + * later to reset the randomizer before each method call. This + * implementation copies the java.util.Random constructor because there is + * no getSeed() there, and seed is protected. + * + * @author Assaf + * @since Aug 6, 2005 + */ + private synchronized static long chooseRandomSeedOnce() + { + return (++seedUniquifier + System.nanoTime()); + } + + /** + * Resets seed to generate the same random stream. + */ + private void resetRandomSeed() + { + this.randomizer.setSeed(this.randomizerSeed); + } + + /** + * (non-Javadoc) + * + * @throws IllegalArgumentException if the aNumOfEdges passed in the + * constructor, cannot be created on a graph of the concrete type with + * aNumOfVertexes. + * org.jgrapht.generate.RandomGraphGenerator.DefaultEdgeTopologyFactory#isNumberOfEdgesValid(org.jgrapht.Graph, + * int) + * + * @see GraphGenerator#generateGraph(Graph, VertexFactory, Map) + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + resetRandomSeed(); + + // key = generation order (1st,2nd,3rd,...) value=vertex Object + // will be used later + Map orderToVertexMap = + new HashMap(this.numOfVertexes); + + for (int i = 0; i < this.numOfVertexes; i++) { + V currVertex = vertexFactory.createVertex(); + target.addVertex(currVertex); + orderToVertexMap.put(Integer.valueOf(i), currVertex); + } + + if (target.vertexSet().size() != numOfVertexes) { + throw new IllegalArgumentException( + "Vertex factory did not produce " + numOfVertexes + + " distinct vertices."); + } + + // use specific type of edge factory, depending of the graph type + // and edge density + EdgeTopologyFactory edgesFactory = + edgeTopologyFactoryChooser(target, numOfEdges); + if (!edgesFactory.isNumberOfEdgesValid(target, numOfEdges)) { + throw new IllegalArgumentException( + "numOfEdges is not valid for the graph type " + + "\n-> Invalid number Of Edges=" + numOfEdges + " for:" + + " graph type=" + target.getClass() + + " ,number Of Vertexes=" + this.numOfVertexes + + "\n-> Advice: For the Max value , check the javadoc for" + + " org.jgrapht.generate.RandomGraphGenerator.DefaultEdgeTopologyFactory"); + } + + edgesFactory.createEdges( + target, + orderToVertexMap, + this.numOfEdges, + this.randomizer); + } + + /** + * Returns a concrete EdgeTopologyFactory, depending on graph type and + * numOfEdges + * + * @param target + * + * @return + */ + private EdgeTopologyFactory edgeTopologyFactoryChooser( + Graph target, + int numOfEdges) + { + return new DefaultEdgeTopologyFactory(); + } + + //~ Inner Interfaces ------------------------------------------------------- + + /** + * This class is used to generate the edge topology for a graph. + * + * @author Assaf + * @since Aug 6, 2005 + */ + public interface EdgeTopologyFactory + { + /** + * Two different calls to the createEdges() with the same parameters + * must result in the generation of the same. But if the randomizer is + * different, it should, usually, create different edge topology. + * + * @param targetGraph - guranteed to start with zero edges. + * @param orderToVertexMap - key=Integer of vertex order . between zero + * to numOfVertexes (exclusive). value = vertex from the graph. unique. + * @param numberOfEdges - to create in the graph + * @param randomizer + */ + public void createEdges( + Graph targetGraph, + Map orderToVertexMap, + int numberOfEdges, + Random randomizer); + + /** + * Checks if the graph can contain the givven numberOfEdges according to + * the graph type restrictions. For example: #V means number of + * vertexes in graph + *

  • a Simple Graph, can have max of #V*(#V-1)/2 edges. etc + * + * @param targetGraph guranteed to start with zero edges. + * @param numberOfEdges + */ + public boolean isNumberOfEdgesValid( + Graph targetGraph, + int numberOfEdges); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Default implementation of the EdgeTopologyFactory interface. randomly + * chooses an edge and tries to add it. If the add fails from any reason + * (like: self edge / multiple edges in unpermitted graph type) it will just + * choose another and try again. Performance: + *
  • when the number of possible edges becomes slim , this class will have + * a very poor performance , cause it will not use gready methods to choose + * them. for example : In simple graph , if #V = N (#x = number Of x) and we + * want full mesh #edges= N*(N-1)/2 , the first added edges will do so + * quickly (O(1) , the last will take O(N^2). So , do not use it in this + * kind of graphs. + *
  • If the numberOfEdges is bigger than what the graph can add, there + * will be an infinite loop here. It is not tested. + * + * @author Assaf + * @since Aug 6, 2005 + */ + public class DefaultEdgeTopologyFactory + implements EdgeTopologyFactory + { + public void createEdges( + Graph targetGraph, + Map orderToVertexMap, + int numberOfEdges, + Random randomizer) + { + int iterationsCounter = 0; + int edgesCounter = 0; + while (edgesCounter < numberOfEdges) { + // randomizer.nextInt(int n) return a number between zero + // (inclusive) and n(exclusive) + VV startVertex = + orderToVertexMap.get( + Integer.valueOf(randomizer.nextInt(numOfVertexes))); + VV endVertex = + orderToVertexMap.get( + Integer.valueOf(randomizer.nextInt(numOfVertexes))); + try { + EE resultEdge = targetGraph.addEdge(startVertex, endVertex); + if (resultEdge != null) { + edgesCounter++; + } + } catch (Exception e) { + // do nothing.just ignore the edge + } + + iterationsCounter++; + } + } + + /** + * checks if the numOfEdges is smaller than the Max edges according to + * the following table: + * + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Graph TypeDirected / UnDirectedmultiple edgesloopsMax Edges
    SimpleGraphUnDirected--N(N-1)/2
    MultigraphUnDirected+-Infinite
    PseudographUnDirected++Infinite
    SimpleDirectedGraphDirected--N (N-1)
    DefaultDirectedGraphDirected-+N*(N-1)+ N = N^2
    DirectedMultigraphDirected++Infinite
    + * + * @see RandomGraphGenerator.EdgeTopologyFactory#isNumberOfEdgesValid(Graph, + * int) + */ + public boolean isNumberOfEdgesValid( + Graph targetGraph, + int numberOfEdges) + { + boolean result; + + boolean infinite = false; + int maxAllowedEdges = getMaxEdgesForVertexNum(targetGraph); + if (maxAllowedEdges == -1) { + infinite = true; + } + + if (true == infinite) { + result = true; + } else if (numberOfEdges <= maxAllowedEdges) { + result = true; + } else { + result = false; + } + return result; + } + + /** + * Return max edges for that graph. If it is infinite return -1 instead. + */ + public int getMaxEdgesForVertexNum(Graph targetGraph) + { + int maxAllowedEdges = 0; + if (targetGraph instanceof SimpleGraph) { + maxAllowedEdges = numOfVertexes * (numOfVertexes - 1) / 2; + } else if (targetGraph instanceof SimpleDirectedGraph) { + maxAllowedEdges = numOfVertexes * (numOfVertexes - 1); + } else if (targetGraph instanceof DefaultDirectedGraph) { + maxAllowedEdges = numOfVertexes * numOfVertexes; + } else { + // This may be overly liberal in the case of something + // like a simple graph which has been wrapped with + // a graph adapter or view. + maxAllowedEdges = -1; // infinite + } + return maxAllowedEdges; + } + } +} + +// End RandomGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/RingGraphGenerator.java b/wdl/org/jgrapht/generate/RingGraphGenerator.java new file mode 100644 index 0000000..927a1b3 --- /dev/null +++ b/wdl/org/jgrapht/generate/RingGraphGenerator.java @@ -0,0 +1,106 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * RingGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a ring graph of any size. A ring graph is a graph that contains a + * single cycle that passes through all its vertices exactly once. For a + * directed graph, the generated edges are oriented consistently around the + * ring. + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public class RingGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int size; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new RingGraphGenerator. + * + * @param size number of vertices to be generated + * + * @throws IllegalArgumentException if the specified size is negative. + */ + public RingGraphGenerator(int size) + { + if (size < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + this.size = size; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + if (size < 1) { + return; + } + + LinearGraphGenerator linearGenerator = + new LinearGraphGenerator(size); + Map privateMap = new HashMap(); + linearGenerator.generateGraph(target, vertexFactory, privateMap); + + V startVertex = privateMap.get(LinearGraphGenerator.START_VERTEX); + V endVertex = privateMap.get(LinearGraphGenerator.END_VERTEX); + target.addEdge(endVertex, startVertex); + } +} + +// End RingGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java b/wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java new file mode 100644 index 0000000..18a1bed --- /dev/null +++ b/wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java @@ -0,0 +1,154 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * ScaleFreeGraphGenerator.java + * ----------------- + * (C) Copyright 2008-2008, by Ilya Razenshteyn and Contributors. + * + * Original Author: Ilya Razenshteyn + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates directed or undirected scale-free network + * of any size. Scale-free network is a connected graph, where degrees of + * vertices are distributed in unusual way. There are many vertices with small + * degrees and only small amount of vertices with big degrees. + * + * @author Ilya Razenshteyn + */ +public class ScaleFreeGraphGenerator + implements GraphGenerator +{ + //~ Instance fields -------------------------------------------------------- + + private int size; // size of graphs, generated by this instance of generator + private long seed; // initial seed + private Random random; // the source of randomness + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructs a new ScaleFreeGraphGenerator. + * + * @param size number of vertices to be generated + */ + public ScaleFreeGraphGenerator( + int size) + { + if (size < 0) { + throw new IllegalArgumentException( + "invalid size: " + size + " (must be non-negative)"); + } + this.size = size; + random = new Random(); + seed = random.nextLong(); + } + + /** + * Constructs a new ScaleFreeGraphGenerator using fixed + * seed for the random generator. + * + * @param size number of vertices to be generated + * @param seed initial seed for the random generator + */ + public ScaleFreeGraphGenerator( + int size, + long seed) + { + if (size < 0) { + throw new IllegalArgumentException( + "invalid size: " + size + " (must be non-negative)"); + } + this.size = size; + random = new Random(); + this.seed = seed; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Generates scale-free network with size passed to the + * constructor. Each call of this method produces identical output (but if + * target is an undirected graph, the directions of edges will be + * lost). + * + * @param target receives the generated edges and vertices; if this is + * non-empty on entry, the result will be a disconnected graph since + * generated elements will not be connected to existing elements + * @param vertexFactory called to produce new vertices + * @param resultMap unused parameter + */ + public void generateGraph( + Graph target, + VertexFactory vertexFactory, + Map resultMap) + { + random.setSeed(seed); + List vertexList = new ArrayList(); + List degrees = new ArrayList(); + int degreeSum = 0; + for (int i = 0; i < size; i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + int newDegree = 0; + while ((newDegree == 0) && (i != 0)) // we want our graph to be + // connected + + { + for (int j = 0; j < vertexList.size(); j++) { + if ((degreeSum == 0) + || (random.nextInt(degreeSum) < degrees.get(j))) + { + degrees.set(j, degrees.get(j) + 1); + newDegree++; + degreeSum += 2; + if (random.nextInt(2) == 0) { + target.addEdge(vertexList.get(j), newVertex); + } else { + target.addEdge(newVertex, vertexList.get(j)); + } + } + } + } + vertexList.add(newVertex); + degrees.add(newDegree); + } + } +} + +// End ScaleFreeGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/StarGraphGenerator.java b/wdl/org/jgrapht/generate/StarGraphGenerator.java new file mode 100644 index 0000000..b6ed2ad --- /dev/null +++ b/wdl/org/jgrapht/generate/StarGraphGenerator.java @@ -0,0 +1,116 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * StarGraphGenerator.java + * ------------------- + * (C) Copyright 2008-2008, by Andrew Newell and Contributors. + * + * Original Author: Andrew Newell + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 24-Dec-2008 : Initial revision (AN); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a star + * graph of any size. This is a graph where every vertex has exactly one + * edge with a center vertex. + * + * @author Andrew Newell + * @since Dec 21, 2008 + */ +public class StarGraphGenerator + implements GraphGenerator +{ + //~ Static fields/initializers --------------------------------------------- + + public static final String CENTER_VERTEX = "Center Vertex"; + + //~ Instance fields -------------------------------------------------------- + + private int order; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new StarGraphGenerator object. + * + * @param order number of total vertices including the center vertex + */ + public StarGraphGenerator(int order) + { + this.order = order; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Generates a star graph with the designated order from the constructor + */ + public void generateGraph( + Graph target, + final VertexFactory vertexFactory, + Map resultMap) + { + if (order < 1) { + return; + } + + //Create center vertex + V centerVertex = vertexFactory.createVertex(); + target.addVertex(centerVertex); + if (resultMap != null) { + resultMap.put(CENTER_VERTEX, centerVertex); + } + + //Create other vertices + for (int i = 0; i < (order - 1); i++) { + V newVertex = vertexFactory.createVertex(); + target.addVertex(newVertex); + } + + //Add one edge between the center vertex and every other vertex + Iterator iter = target.vertexSet().iterator(); + while (iter.hasNext()) { + V v = iter.next(); + if (v != centerVertex) { + target.addEdge(v, centerVertex); + } + } + } +} + +// End StarGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/WheelGraphGenerator.java b/wdl/org/jgrapht/generate/WheelGraphGenerator.java new file mode 100644 index 0000000..2582333 --- /dev/null +++ b/wdl/org/jgrapht/generate/WheelGraphGenerator.java @@ -0,0 +1,155 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * WheelGraphGenerator.java + * ------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sep-2003 : Initial revision (JVS); + * + */ +package org.jgrapht.generate; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Generates a wheel + * graph of any size. Reminding a bicycle wheel, a wheel graph has a hub + * vertex in the center and a rim of vertices around it that are connected to + * each other (as a ring). The rim vertices are also connected to the hub with + * edges that are called "spokes". + * + * @author John V. Sichi + * @since Sep 16, 2003 + */ +public class WheelGraphGenerator + implements GraphGenerator +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Role for the hub vertex. + */ + public static final String HUB_VERTEX = "Hub Vertex"; + + //~ Instance fields -------------------------------------------------------- + + private boolean inwardSpokes; + private int size; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new WheelGraphGenerator object. This constructor is more + * suitable for undirected graphs, where spokes' direction is meaningless. + * In the directed case, spokes will be oriented from rim to hub. + * + * @param size number of vertices to be generated. + */ + public WheelGraphGenerator(int size) + { + this(size, true); + } + + /** + * Construct a new WheelGraphGenerator. + * + * @param size number of vertices to be generated. + * @param inwardSpokes if true and graph is directed, spokes + * are oriented from rim to hub; else from hub to rim. + * + * @throws IllegalArgumentException + */ + public WheelGraphGenerator(int size, boolean inwardSpokes) + { + if (size < 0) { + throw new IllegalArgumentException("must be non-negative"); + } + + this.size = size; + this.inwardSpokes = inwardSpokes; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public void generateGraph( + Graph target, + final VertexFactory vertexFactory, + Map resultMap) + { + if (size < 1) { + return; + } + + // A little trickery to intercept the rim generation. This is + // necessary since target may be initially non-empty, meaning we can't + // rely on its vertex set after the rim is generated. + final Collection rim = new ArrayList(); + VertexFactory rimVertexFactory = + new VertexFactory() { + public V createVertex() + { + V vertex = vertexFactory.createVertex(); + rim.add(vertex); + + return vertex; + } + }; + + RingGraphGenerator ringGenerator = + new RingGraphGenerator(size - 1); + ringGenerator.generateGraph(target, rimVertexFactory, resultMap); + + V hubVertex = vertexFactory.createVertex(); + target.addVertex(hubVertex); + + if (resultMap != null) { + resultMap.put(HUB_VERTEX, hubVertex); + } + + for (V rimVertex : rim) { + if (inwardSpokes) { + target.addEdge(rimVertex, hubVertex); + } else { + target.addEdge(hubVertex, rimVertex); + } + } + } +} + +// End WheelGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/package.html b/wdl/org/jgrapht/generate/package.html new file mode 100644 index 0000000..cde8047 --- /dev/null +++ b/wdl/org/jgrapht/generate/package.html @@ -0,0 +1,6 @@ + + + +Generators for graphs of various topologies. + + \ No newline at end of file diff --git a/wdl/org/jgrapht/graph/AbstractBaseGraph.java b/wdl/org/jgrapht/graph/AbstractBaseGraph.java new file mode 100644 index 0000000..277be87 --- /dev/null +++ b/wdl/org/jgrapht/graph/AbstractBaseGraph.java @@ -0,0 +1,1222 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * AbstractBaseGraph.java + * ---------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): John V. Sichi + * Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 10-Aug-2003 : General edge refactoring (BN); + * 06-Nov-2003 : Change edge sharing semantics (JVS); + * 07-Feb-2004 : Enabled serialization (BN); + * 11-Mar-2004 : Made generic (CH); + * 01-Jun-2005 : Added EdgeListFactory (JVS); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * The most general implementation of the {@link org.jgrapht.Graph} interface. + * Its subclasses add various restrictions to get more specific graphs. The + * decision whether it is directed or undirected is decided at construction time + * and cannot be later modified (see constructor for details). + * + *

    This graph implementation guarantees deterministic vertex and edge set + * ordering (via {@link LinkedHashMap} and {@link LinkedHashSet}).

    + * + * @author Barak Naveh + * @since Jul 24, 2003 + */ +public abstract class AbstractBaseGraph + extends AbstractGraph + implements Graph, + Cloneable, + Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -1263088497616142427L; + + private static final String LOOPS_NOT_ALLOWED = "loops not allowed"; + + //~ Instance fields -------------------------------------------------------- + + boolean allowingLoops; + + private EdgeFactory edgeFactory; + private EdgeSetFactory edgeSetFactory; + private Map edgeMap; + private transient Set unmodifiableEdgeSet = null; + private transient Set unmodifiableVertexSet = null; + private Specifics specifics; + private boolean allowingMultipleEdges; + + private transient TypeUtil vertexTypeDecl = null; + + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new pseudograph. The pseudograph can either be directed or + * undirected, depending on the specified edge factory. + * + * @param ef the edge factory of the new graph. + * @param allowMultipleEdges whether to allow multiple edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * + * @throws NullPointerException if the specified edge factory is + * null. + */ + public AbstractBaseGraph( + EdgeFactory ef, + boolean allowMultipleEdges, + boolean allowLoops) + { + if (ef == null) { + throw new NullPointerException(); + } + + edgeMap = new LinkedHashMap(); + edgeFactory = ef; + allowingLoops = allowLoops; + allowingMultipleEdges = allowMultipleEdges; + + specifics = createSpecifics(); + + this.edgeSetFactory = new ArrayListFactory(); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + return specifics.getAllEdges(sourceVertex, targetVertex); + } + + /** + * Returns true if and only if self-loops are allowed in this + * graph. A self loop is an edge that its source and target vertices are the + * same. + * + * @return true if and only if graph loops are allowed. + */ + public boolean isAllowingLoops() + { + return allowingLoops; + } + + /** + * Returns true if and only if multiple edges are allowed in + * this graph. The meaning of multiple edges is that there can be many edges + * going from vertex v1 to vertex v2. + * + * @return true if and only if multiple edges are allowed. + */ + public boolean isAllowingMultipleEdges() + { + return allowingMultipleEdges; + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + return specifics.getEdge(sourceVertex, targetVertex); + } + + /** + * @see Graph#getEdgeFactory() + */ + public EdgeFactory getEdgeFactory() + { + return edgeFactory; + } + + /** + * Set the {@link EdgeSetFactory} to use for this graph. Initially, a graph + * is created with a default implementation which always supplies an {@link + * java.util.ArrayList} with capacity 1. + * + * @param edgeSetFactory factory to use for subsequently created edge sets + * (this call has no effect on existing edge sets) + */ + public void setEdgeSetFactory(EdgeSetFactory edgeSetFactory) + { + this.edgeSetFactory = edgeSetFactory; + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + assertVertexExist(sourceVertex); + assertVertexExist(targetVertex); + + if (!allowingMultipleEdges + && containsEdge(sourceVertex, targetVertex)) + { + return null; + } + + if (!allowingLoops && sourceVertex.equals(targetVertex)) { + throw new IllegalArgumentException(LOOPS_NOT_ALLOWED); + } + + E e = edgeFactory.createEdge(sourceVertex, targetVertex); + + if (containsEdge(e)) { // this restriction should stay! + + return null; + } else { + IntrusiveEdge intrusiveEdge = + createIntrusiveEdge(e, sourceVertex, targetVertex); + + edgeMap.put(e, intrusiveEdge); + specifics.addEdgeToTouchingVertices(e); + + return e; + } + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + if (e == null) { + throw new NullPointerException(); + } else if (containsEdge(e)) { + return false; + } + + assertVertexExist(sourceVertex); + assertVertexExist(targetVertex); + + if (!allowingMultipleEdges + && containsEdge(sourceVertex, targetVertex)) + { + return false; + } + + if (!allowingLoops && sourceVertex.equals(targetVertex)) { + throw new IllegalArgumentException(LOOPS_NOT_ALLOWED); + } + + IntrusiveEdge intrusiveEdge = + createIntrusiveEdge(e, sourceVertex, targetVertex); + + edgeMap.put(e, intrusiveEdge); + specifics.addEdgeToTouchingVertices(e); + + return true; + } + + private IntrusiveEdge createIntrusiveEdge( + E e, + V sourceVertex, + V targetVertex) + { + IntrusiveEdge intrusiveEdge; + if (e instanceof IntrusiveEdge) { + intrusiveEdge = (IntrusiveEdge) e; + } else { + intrusiveEdge = new IntrusiveEdge(); + } + intrusiveEdge.source = sourceVertex; + intrusiveEdge.target = targetVertex; + return intrusiveEdge; + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + if (v == null) { + throw new NullPointerException(); + } else if (containsVertex(v)) { + return false; + } else { + specifics.addVertex(v); + + return true; + } + } + + /** + * @see Graph#getEdgeSource(Object) + */ + public V getEdgeSource(E e) + { + return TypeUtil.uncheckedCast( + getIntrusiveEdge(e).source, + vertexTypeDecl); + } + + /** + * @see Graph#getEdgeTarget(Object) + */ + public V getEdgeTarget(E e) + { + return TypeUtil.uncheckedCast( + getIntrusiveEdge(e).target, + vertexTypeDecl); + } + + private IntrusiveEdge getIntrusiveEdge(E e) + { + if (e instanceof IntrusiveEdge) { + return (IntrusiveEdge) e; + } + + return edgeMap.get(e); + } + + /** + * Returns a shallow copy of this graph instance. Neither edges nor vertices + * are cloned. + * + * @return a shallow copy of this set. + * + * @throws RuntimeException + * + * @see java.lang.Object#clone() + */ + public Object clone() + { + try { + TypeUtil> typeDecl = null; + + AbstractBaseGraph newGraph = + TypeUtil.uncheckedCast(super.clone(), typeDecl); + + newGraph.edgeMap = new LinkedHashMap(); + + newGraph.edgeFactory = this.edgeFactory; + newGraph.unmodifiableEdgeSet = null; + newGraph.unmodifiableVertexSet = null; + + // NOTE: it's important for this to happen in an object + // method so that the new inner class instance gets associated with + // the right outer class instance + newGraph.specifics = newGraph.createSpecifics(); + + Graphs.addGraph(newGraph, this); + + return newGraph; + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + throw new RuntimeException(); + } + } + + /** + * @see Graph#containsEdge(Object) + */ + public boolean containsEdge(E e) + { + return edgeMap.containsKey(e); + } + + /** + * @see Graph#containsVertex(Object) + */ + public boolean containsVertex(V v) + { + return specifics.getVertexSet().contains(v); + } + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + return specifics.degreeOf(vertex); + } + + /** + * @see Graph#edgeSet() + */ + public Set edgeSet() + { + if (unmodifiableEdgeSet == null) { + unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet()); + } + + return unmodifiableEdgeSet; + } + + /** + * @see Graph#edgesOf(Object) + */ + public Set edgesOf(V vertex) + { + return specifics.edgesOf(vertex); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + return specifics.inDegreeOf(vertex); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + return specifics.incomingEdgesOf(vertex); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + return specifics.outDegreeOf(vertex); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + return specifics.outgoingEdgesOf(vertex); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + E e = getEdge(sourceVertex, targetVertex); + + if (e != null) { + specifics.removeEdgeFromTouchingVertices(e); + edgeMap.remove(e); + } + + return e; + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + if (containsEdge(e)) { + specifics.removeEdgeFromTouchingVertices(e); + edgeMap.remove(e); + + return true; + } else { + return false; + } + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + if (containsVertex(v)) { + Set touchingEdgesList = edgesOf(v); + + // cannot iterate over list - will cause + // ConcurrentModificationException + removeAllEdges(new ArrayList(touchingEdgesList)); + + specifics.getVertexSet().remove(v); // remove the vertex itself + + return true; + } else { + return false; + } + } + + /** + * @see Graph#vertexSet() + */ + public Set vertexSet() + { + if (unmodifiableVertexSet == null) { + unmodifiableVertexSet = + Collections.unmodifiableSet(specifics.getVertexSet()); + } + + return unmodifiableVertexSet; + } + + /** + * @see Graph#getEdgeWeight(Object) + */ + public double getEdgeWeight(E e) + { + if (e instanceof DefaultWeightedEdge) { + return ((DefaultWeightedEdge) e).getWeight(); + } else { + return WeightedGraph.DEFAULT_EDGE_WEIGHT; + } + } + + /** + * @see WeightedGraph#setEdgeWeight(Object, double) + */ + public void setEdgeWeight(E e, double weight) + { + assert (e instanceof DefaultWeightedEdge) : e.getClass(); + ((DefaultWeightedEdge) e).weight = weight; + } + + private Specifics createSpecifics() + { + if (this instanceof DirectedGraph) { + return new DirectedSpecifics(); + } else if (this instanceof UndirectedGraph) { + return new UndirectedSpecifics(); + } else { + throw new IllegalArgumentException( + "must be instance of either DirectedGraph or UndirectedGraph"); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * . + * + * @author Barak Naveh + */ + private abstract class Specifics + implements Serializable + { + private static final long serialVersionUID = 785196247314761183L; + + public abstract void addVertex(V vertex); + + public abstract Set getVertexSet(); + + /** + * . + * + * @param sourceVertex + * @param targetVertex + * + * @return + */ + public abstract Set getAllEdges(V sourceVertex, + V targetVertex); + + /** + * . + * + * @param sourceVertex + * @param targetVertex + * + * @return + */ + public abstract E getEdge(V sourceVertex, V targetVertex); + + /** + * Adds the specified edge to the edge containers of its source and + * target vertices. + * + * @param e + */ + public abstract void addEdgeToTouchingVertices(E e); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract int degreeOf(V vertex); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract Set edgesOf(V vertex); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract int inDegreeOf(V vertex); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract Set incomingEdgesOf(V vertex); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract int outDegreeOf(V vertex); + + /** + * . + * + * @param vertex + * + * @return + */ + public abstract Set outgoingEdgesOf(V vertex); + + /** + * Removes the specified edge from the edge containers of its source and + * target vertices. + * + * @param e + */ + public abstract void removeEdgeFromTouchingVertices(E e); + } + + private static class ArrayListFactory + implements EdgeSetFactory, + Serializable + { + private static final long serialVersionUID = 5936902837403445985L; + + /** + * @see EdgeSetFactory.createEdgeSet + */ + public Set createEdgeSet(VV vertex) + { + // NOTE: use size 1 to keep memory usage under control + // for the common case of vertices with low degree + return new ArrayUnenforcedSet(1); + } + } + + /** + * A container for vertex edges. + * + *

    In this edge container we use array lists to minimize memory toll. + * However, for high-degree vertices we replace the entire edge container + * with a direct access subclass (to be implemented).

    + * + * @author Barak Naveh + */ + private static class DirectedEdgeContainer + implements Serializable + { + private static final long serialVersionUID = 7494242245729767106L; + Set incoming; + Set outgoing; + private transient Set unmodifiableIncoming = null; + private transient Set unmodifiableOutgoing = null; + + DirectedEdgeContainer(EdgeSetFactory edgeSetFactory, + VV vertex) + { + incoming = edgeSetFactory.createEdgeSet(vertex); + outgoing = edgeSetFactory.createEdgeSet(vertex); + } + + /** + * A lazy build of unmodifiable incoming edge set. + * + * @return + */ + public Set getUnmodifiableIncomingEdges() + { + if (unmodifiableIncoming == null) { + unmodifiableIncoming = Collections.unmodifiableSet(incoming); + } + + return unmodifiableIncoming; + } + + /** + * A lazy build of unmodifiable outgoing edge set. + * + * @return + */ + public Set getUnmodifiableOutgoingEdges() + { + if (unmodifiableOutgoing == null) { + unmodifiableOutgoing = Collections.unmodifiableSet(outgoing); + } + + return unmodifiableOutgoing; + } + + /** + * . + * + * @param e + */ + public void addIncomingEdge(EE e) + { + incoming.add(e); + } + + /** + * . + * + * @param e + */ + public void addOutgoingEdge(EE e) + { + outgoing.add(e); + } + + /** + * . + * + * @param e + */ + public void removeIncomingEdge(EE e) + { + incoming.remove(e); + } + + /** + * . + * + * @param e + */ + public void removeOutgoingEdge(EE e) + { + outgoing.remove(e); + } + } + + /** + * . + * + * @author Barak Naveh + */ + private class DirectedSpecifics + extends Specifics + implements Serializable + { + private static final long serialVersionUID = 8971725103718958232L; + private static final String NOT_IN_DIRECTED_GRAPH = + "no such operation in a directed graph"; + + private Map> vertexMapDirected = + new LinkedHashMap>(); + + public void addVertex(V v) + { + // add with a lazy edge container entry + vertexMapDirected.put(v, null); + } + + public Set getVertexSet() + { + return vertexMapDirected.keySet(); + } + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (containsVertex(sourceVertex) + && containsVertex(targetVertex)) + { + edges = new ArrayUnenforcedSet(); + + DirectedEdgeContainer ec = getEdgeContainer(sourceVertex); + + Iterator iter = ec.outgoing.iterator(); + + while (iter.hasNext()) { + E e = iter.next(); + + if (getEdgeTarget(e).equals(targetVertex)) { + edges.add(e); + } + } + } + + return edges; + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + if (containsVertex(sourceVertex) + && containsVertex(targetVertex)) + { + DirectedEdgeContainer ec = getEdgeContainer(sourceVertex); + + Iterator iter = ec.outgoing.iterator(); + + while (iter.hasNext()) { + E e = iter.next(); + + if (getEdgeTarget(e).equals(targetVertex)) { + return e; + } + } + } + + return null; + } + + /** + * @see AbstractBaseGraph#addEdgeToTouchingVertices(Edge) + */ + public void addEdgeToTouchingVertices(E e) + { + V source = getEdgeSource(e); + V target = getEdgeTarget(e); + + getEdgeContainer(source).addOutgoingEdge(e); + getEdgeContainer(target).addIncomingEdge(e); + } + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + throw new UnsupportedOperationException(NOT_IN_DIRECTED_GRAPH); + } + + /** + * @see Graph#edgesOf(Object) + */ + public Set edgesOf(V vertex) + { + ArrayUnenforcedSet inAndOut = + new ArrayUnenforcedSet(getEdgeContainer(vertex).incoming); + inAndOut.addAll(getEdgeContainer(vertex).outgoing); + + // we have two copies for each self-loop - remove one of them. + if (allowingLoops) { + Set loops = getAllEdges(vertex, vertex); + + for (int i = 0; i < inAndOut.size();) { + Object e = inAndOut.get(i); + + if (loops.contains(e)) { + inAndOut.remove(i); + loops.remove(e); // so we remove it only once + } else { + i++; + } + } + } + + return Collections.unmodifiableSet(inAndOut); + } + + /** + * @see DirectedGraph#inDegree(Object) + */ + public int inDegreeOf(V vertex) + { + return getEdgeContainer(vertex).incoming.size(); + } + + /** + * @see DirectedGraph#incomingEdges(Object) + */ + public Set incomingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableIncomingEdges(); + } + + /** + * @see DirectedGraph#outDegree(Object) + */ + public int outDegreeOf(V vertex) + { + return getEdgeContainer(vertex).outgoing.size(); + } + + /** + * @see DirectedGraph#outgoingEdges(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableOutgoingEdges(); + } + + /** + * @see AbstractBaseGraph#removeEdgeFromTouchingVertices(Edge) + */ + public void removeEdgeFromTouchingVertices(E e) + { + V source = getEdgeSource(e); + V target = getEdgeTarget(e); + + getEdgeContainer(source).removeOutgoingEdge(e); + getEdgeContainer(target).removeIncomingEdge(e); + } + + /** + * A lazy build of edge container for specified vertex. + * + * @param vertex a vertex in this graph. + * + * @return EdgeContainer + */ + private DirectedEdgeContainer getEdgeContainer(V vertex) + { + assertVertexExist(vertex); + + DirectedEdgeContainer ec = vertexMapDirected.get(vertex); + + if (ec == null) { + ec = new DirectedEdgeContainer(edgeSetFactory, vertex); + vertexMapDirected.put(vertex, ec); + } + + return ec; + } + } + + /** + * A container of for vertex edges. + * + *

    In this edge container we use array lists to minimize memory toll. + * However, for high-degree vertices we replace the entire edge container + * with a direct access subclass (to be implemented).

    + * + * @author Barak Naveh + */ + private static class UndirectedEdgeContainer + implements Serializable + { + private static final long serialVersionUID = -6623207588411170010L; + Set vertexEdges; + private transient Set unmodifiableVertexEdges = null; + + UndirectedEdgeContainer( + EdgeSetFactory edgeSetFactory, + VV vertex) + { + vertexEdges = edgeSetFactory.createEdgeSet(vertex); + } + + /** + * A lazy build of unmodifiable list of vertex edges + * + * @return + */ + public Set getUnmodifiableVertexEdges() + { + if (unmodifiableVertexEdges == null) { + unmodifiableVertexEdges = + Collections.unmodifiableSet(vertexEdges); + } + + return unmodifiableVertexEdges; + } + + /** + * . + * + * @param e + */ + public void addEdge(EE e) + { + vertexEdges.add(e); + } + + /** + * . + * + * @return + */ + public int edgeCount() + { + return vertexEdges.size(); + } + + /** + * . + * + * @param e + */ + public void removeEdge(EE e) + { + vertexEdges.remove(e); + } + } + + /** + * . + * + * @author Barak Naveh + */ + private class UndirectedSpecifics + extends Specifics + implements Serializable + { + private static final long serialVersionUID = 6494588405178655873L; + private static final String NOT_IN_UNDIRECTED_GRAPH = + "no such operation in an undirected graph"; + + private Map> vertexMapUndirected = + new LinkedHashMap>(); + + public void addVertex(V v) + { + // add with a lazy edge container entry + vertexMapUndirected.put(v, null); + } + + public Set getVertexSet() + { + return vertexMapUndirected.keySet(); + } + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (containsVertex(sourceVertex) + && containsVertex(targetVertex)) + { + edges = new ArrayUnenforcedSet(); + + Iterator iter = + getEdgeContainer(sourceVertex).vertexEdges.iterator(); + + while (iter.hasNext()) { + E e = iter.next(); + + boolean equalStraight = + sourceVertex.equals(getEdgeSource(e)) + && targetVertex.equals(getEdgeTarget(e)); + + boolean equalInverted = + sourceVertex.equals(getEdgeTarget(e)) + && targetVertex.equals(getEdgeSource(e)); + + if (equalStraight || equalInverted) { + edges.add(e); + } + } + } + + return edges; + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + if (containsVertex(sourceVertex) + && containsVertex(targetVertex)) + { + Iterator iter = + getEdgeContainer(sourceVertex).vertexEdges.iterator(); + + while (iter.hasNext()) { + E e = iter.next(); + + boolean equalStraight = + sourceVertex.equals(getEdgeSource(e)) + && targetVertex.equals(getEdgeTarget(e)); + + boolean equalInverted = + sourceVertex.equals(getEdgeTarget(e)) + && targetVertex.equals(getEdgeSource(e)); + + if (equalStraight || equalInverted) { + return e; + } + } + } + + return null; + } + + /** + * @see AbstractBaseGraph#addEdgeToTouchingVertices(Edge) + */ + public void addEdgeToTouchingVertices(E e) + { + V source = getEdgeSource(e); + V target = getEdgeTarget(e); + + getEdgeContainer(source).addEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).addEdge(e); + } + } + + /** + * @see UndirectedGraph#degreeOf(V) + */ + public int degreeOf(V vertex) + { + if (allowingLoops) { // then we must count, and add loops twice + + int degree = 0; + Set edges = getEdgeContainer(vertex).vertexEdges; + + for (E e : edges) { + if (getEdgeSource(e).equals(getEdgeTarget(e))) { + degree += 2; + } else { + degree += 1; + } + } + + return degree; + } else { + return getEdgeContainer(vertex).edgeCount(); + } + } + + /** + * @see Graph#edgesOf(V) + */ + public Set edgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); + } + + /** + * @see AbstractBaseGraph#removeEdgeFromTouchingVertices(Edge) + */ + public void removeEdgeFromTouchingVertices(E e) + { + V source = getEdgeSource(e); + V target = getEdgeTarget(e); + + getEdgeContainer(source).removeEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).removeEdge(e); + } + } + + /** + * A lazy build of edge container for specified vertex. + * + * @param vertex a vertex in this graph. + * + * @return EdgeContainer + */ + private UndirectedEdgeContainer getEdgeContainer(V vertex) + { + assertVertexExist(vertex); + + UndirectedEdgeContainer ec = vertexMapUndirected.get(vertex); + + if (ec == null) { + ec = new UndirectedEdgeContainer( + edgeSetFactory, + vertex); + vertexMapUndirected.put(vertex, ec); + } + + return ec; + } + } +} + +// End AbstractBaseGraph.java diff --git a/wdl/org/jgrapht/graph/AbstractGraph.java b/wdl/org/jgrapht/graph/AbstractGraph.java new file mode 100644 index 0000000..268efcc --- /dev/null +++ b/wdl/org/jgrapht/graph/AbstractGraph.java @@ -0,0 +1,322 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * AbstractGraph.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * Vladimir Kostyukov + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * 14-Jun-2012 : Added hashCode() and equals() methods implementation (VK); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * A skeletal implementation of the Graph interface, to minimize the + * effort required to implement graph interfaces. This implementation is + * applicable to both: directed graphs and undirected graphs. + * + * @author Barak Naveh + * @see Graph + * @see DirectedGraph + * @see UndirectedGraph + */ +public abstract class AbstractGraph + implements Graph +{ + //~ Constructors ----------------------------------------------------------- + + /** + * Construct a new empty graph object. + */ + public AbstractGraph() + { + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#containsEdge(Object, Object) + */ + public boolean containsEdge(V sourceVertex, V targetVertex) + { + return getEdge(sourceVertex, targetVertex) != null; + } + + /** + * @see Graph#removeAllEdges(Collection) + */ + public boolean removeAllEdges(Collection edges) + { + boolean modified = false; + + for (E e : edges) { + modified |= removeEdge(e); + } + + return modified; + } + + /** + * @see Graph#removeAllEdges(Object, Object) + */ + public Set removeAllEdges(V sourceVertex, V targetVertex) + { + Set removed = getAllEdges(sourceVertex, targetVertex); + removeAllEdges(removed); + + return removed; + } + + /** + * @see Graph#removeAllVertices(Collection) + */ + public boolean removeAllVertices(Collection vertices) + { + boolean modified = false; + + for (V v : vertices) { + modified |= removeVertex(v); + } + + return modified; + } + + /** + * Returns a string of the parenthesized pair (V, E) representing this + * G=(V,E) graph. 'V' is the string representation of the vertex set, and + * 'E' is the string representation of the edge set. + * + * @return a string representation of this graph. + */ + public String toString() + { + return toStringFromSets( + vertexSet(), + edgeSet(), + (this instanceof DirectedGraph)); + } + + /** + * Ensures that the specified vertex exists in this graph, or else throws + * exception. + * + * @param v vertex + * + * @return true if this assertion holds. + * + * @throws NullPointerException if specified vertex is null. + * @throws IllegalArgumentException if specified vertex does not exist in + * this graph. + */ + protected boolean assertVertexExist(V v) + { + if (containsVertex(v)) { + return true; + } else if (v == null) { + throw new NullPointerException(); + } else { + throw new IllegalArgumentException("no such vertex in graph"); + } + } + + /** + * Removes all the edges in this graph that are also contained in the + * specified edge array. After this call returns, this graph will contain no + * edges in common with the specified edges. This method will invoke the + * {@link Graph#removeEdge(Object)} method. + * + * @param edges edges to be removed from this graph. + * + * @return true if this graph changed as a result of the call. + * + * @see Graph#removeEdge(Object) + * @see Graph#containsEdge(Object) + */ + protected boolean removeAllEdges(E [] edges) + { + boolean modified = false; + + for (int i = 0; i < edges.length; i++) { + modified |= removeEdge(edges[i]); + } + + return modified; + } + + /** + * Helper for subclass implementations of toString( ). + * + * @param vertexSet the vertex set V to be printed + * @param edgeSet the edge set E to be printed + * @param directed true to use parens for each edge (representing directed); + * false to use curly braces (representing undirected) + * + * @return a string representation of (V,E) + */ + protected String toStringFromSets( + Collection vertexSet, + Collection edgeSet, + boolean directed) + { + List renderedEdges = new ArrayList(); + + StringBuffer sb = new StringBuffer(); + for (E e : edgeSet) { + if ((e.getClass() != DefaultEdge.class) + && (e.getClass() != DefaultWeightedEdge.class)) + { + sb.append(e.toString()); + sb.append("="); + } + if (directed) { + sb.append("("); + } else { + sb.append("{"); + } + sb.append(getEdgeSource(e)); + sb.append(","); + sb.append(getEdgeTarget(e)); + if (directed) { + sb.append(")"); + } else { + sb.append("}"); + } + + // REVIEW jvs 29-May-2006: dump weight somewhere? + renderedEdges.add(sb.toString()); + sb.setLength(0); + } + + return "(" + vertexSet + ", " + renderedEdges + ")"; + } + + /** + * Returns a hash code value for this graph. The hash code of a graph is + * defined to be the sum of the hash codes of vertices and edges in the + * graph. It is also based on graph topology and edges weights. + * + * @return the hash code value this graph + * + * @see {@link Object#equals(Object)}, {@link Object#hashCode()} + */ + public int hashCode() + { + int hash = vertexSet().hashCode(); + + for (E e: edgeSet()) { + + int part = e.hashCode(); + + int source = getEdgeSource(e).hashCode(); + int target = getEdgeTarget(e).hashCode(); + + // see http://en.wikipedia.org/wiki/Pairing_function (VK); + int pairing = ((source + target) * + (source + target + 1) / 2) + target; + part = 27 * part + pairing; + + long weight = (long) getEdgeWeight(e); + part = 27 * part + (int) (weight ^ (weight >>> 32)); + + hash += part; + } + + return hash; + } + + /** + * Indicates whether some other object is "equal to" this graph. + * Returns true if the given object is also a graph, + * the two graphs are instances of the same graph class, + * have identical vertices and edges sets with the same weights. + * + * @param obj object to be compared for equality with this graph + * + * @return true if the specified object is equal to this graph + * + * @see {@link Object#equals(Object)}, {@link Object#hashCode()} + */ + public boolean equals(Object obj) + { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + TypeUtil> typeDecl = null; + Graph g = TypeUtil.uncheckedCast(obj, typeDecl); + + if (!vertexSet().equals(g.vertexSet())) { + return false; + } + if (edgeSet().size() != g.edgeSet().size()) { + return false; + } + + for (E e: edgeSet()) { + + V source = getEdgeSource(e); + V target = getEdgeTarget(e); + + if (!g.containsEdge(e)) { + return false; + } + + if (!g.getEdgeSource(e).equals(source) + || !g.getEdgeTarget(e).equals(target)) + { + return false; + } + + if (Math.abs(getEdgeWeight(e) - g.getEdgeWeight(e)) > 10e-7) { + return false; + } + } + + return true; + } +} + +// End AbstractGraph.java diff --git a/wdl/org/jgrapht/graph/AsUndirectedGraph.java b/wdl/org/jgrapht/graph/AsUndirectedGraph.java new file mode 100644 index 0000000..208441b --- /dev/null +++ b/wdl/org/jgrapht/graph/AsUndirectedGraph.java @@ -0,0 +1,209 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * AsUndirectedGraph.java + * ---------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 14-Aug-2003 : Initial revision (JVS); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * An undirected view of the backing directed graph specified in the + * constructor. This graph allows modules to apply algorithms designed for + * undirected graphs to a directed graph by simply ignoring edge direction. If + * the backing directed graph is an oriented graph, + * then the view will be a simple graph; otherwise, it will be a multigraph. + * Query operations on this graph "read through" to the backing graph. Attempts + * to add edges will result in an UnsupportedOperationException, + * but vertex addition/removal and edge removal are all supported (and + * immediately reflected in the backing graph). + * + *

    Note that edges returned by this graph's accessors are really just the + * edges of the underlying directed graph. Since there is no interface + * distinction between directed and undirected edges, this detail should be + * irrelevant to algorithms.

    + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods. This graph will be serializable if the backing + * graph is serializable.

    + * + * @author John V. Sichi + * @since Aug 14, 2003 + */ +public class AsUndirectedGraph + extends GraphDelegator + implements Serializable, + UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3257845485078065462L; // @todo renew + private static final String NO_EDGE_ADD = + "this graph does not support edge addition"; + private static final String UNDIRECTED = + "this graph only supports undirected operations"; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for AsUndirectedGraph. + * + * @param g the backing directed graph over which an undirected view is to + * be created. + */ + public AsUndirectedGraph(DirectedGraph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set forwardList = super.getAllEdges(sourceVertex, targetVertex); + + if (sourceVertex.equals(targetVertex)) { + // avoid duplicating loops + return forwardList; + } + + Set reverseList = super.getAllEdges(targetVertex, sourceVertex); + Set list = + new ArrayUnenforcedSet( + forwardList.size() + reverseList.size()); + list.addAll(forwardList); + list.addAll(reverseList); + + return list; + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + E edge = super.getEdge(sourceVertex, targetVertex); + + if (edge != null) { + return edge; + } + + // try the other direction + return super.getEdge(targetVertex, sourceVertex); + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(NO_EDGE_ADD); + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + throw new UnsupportedOperationException(NO_EDGE_ADD); + } + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + // this counts loops twice, which is consistent with AbstractBaseGraph + return super.inDegreeOf(vertex) + super.outDegreeOf(vertex); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + throw new UnsupportedOperationException(UNDIRECTED); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + throw new UnsupportedOperationException(UNDIRECTED); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + throw new UnsupportedOperationException(UNDIRECTED); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + throw new UnsupportedOperationException(UNDIRECTED); + } + + /** + * @see AbstractBaseGraph#toString() + */ + public String toString() + { + return super.toStringFromSets(vertexSet(), edgeSet(), false); + } +} + +// End AsUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java b/wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java new file mode 100644 index 0000000..be56777 --- /dev/null +++ b/wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java @@ -0,0 +1,100 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * AsUnweightedGraph.java + * ---------------------- + * (C) Copyright 2007-2008, by Lucas J. Scharenbroich and Contributors. + * + * Original Author: Lucas J. Scharenbroich + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 7-Sep-2007 : Initial revision (LJS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import org.jgrapht.*; + + +/** + * An unweighted view of the backing weighted graph specified in the + * constructor. This graph allows modules to apply algorithms designed for + * unweighted graphs to a weighted graph by simply ignoring edge weights. Query + * operations on this graph "read through" to the backing graph. Vertex + * addition/removal and edge addition/removal are all supported (and immediately + * reflected in the backing graph). + * + *

    Note that edges returned by this graph's accessors are really just the + * edges of the underlying directed graph.

    + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods. This graph will be serializable if the backing + * graph is serializable.

    + * + * @author Lucas J. Scharenbroich + * @since Sep 7, 2007 + */ +public class AsUnweightedDirectedGraph + extends GraphDelegator + implements Serializable, + DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = -4320818446777715312L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for AsUnweightedGraph. + * + * @param g the backing graph over which an unweighted view is to be + * created. + */ + public AsUnweightedDirectedGraph(DirectedGraph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getEdgeWeight + */ + public double getEdgeWeight(E e) + { + return WeightedGraph.DEFAULT_EDGE_WEIGHT; + } +} + +// End AsUnweightedDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/AsUnweightedGraph.java b/wdl/org/jgrapht/graph/AsUnweightedGraph.java new file mode 100644 index 0000000..7ee6af9 --- /dev/null +++ b/wdl/org/jgrapht/graph/AsUnweightedGraph.java @@ -0,0 +1,100 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * AsUnweightedGraph.java + * ---------------------- + * (C) Copyright 2007-2008, by Lucas J. Scharenbroich and Contributors. + * + * Original Author: Lucas J. Scharenbroich + * Contributor(s): John V. Sichi +* + * $Id$ + * + * Changes + * ------- + * 7-Sep-2007 : Initial revision (LJS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import org.jgrapht.*; + + +/** + * An unweighted view of the backing weighted graph specified in the + * constructor. This graph allows modules to apply algorithms designed for + * unweighted graphs to a weighted graph by simply ignoring edge weights. Query + * operations on this graph "read through" to the backing graph. Vertex + * addition/removal and edge addition/removal are all supported (and immediately + * reflected in the backing graph). + * + *

    Note that edges returned by this graph's accessors are really just the + * edges of the underlying directed graph.

    + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods. This graph will be serializable if the backing + * graph is serializable.

    + * + * @author Lucas J. Scharenbroich + * @since Sep 7, 2007 + */ + +public class AsUnweightedGraph + extends GraphDelegator + implements Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = 7175505077601824663L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for AsUnweightedGraph. + * + * @param g the backing graph over which an unweighted view is to be + * created. + */ + public AsUnweightedGraph(Graph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getEdgeWeight + */ + public double getEdgeWeight(E e) + { + return WeightedGraph.DEFAULT_EDGE_WEIGHT; + } +} + +// End AsUnweightedGraph.java diff --git a/wdl/org/jgrapht/graph/AsWeightedGraph.java b/wdl/org/jgrapht/graph/AsWeightedGraph.java new file mode 100644 index 0000000..54fbaf1 --- /dev/null +++ b/wdl/org/jgrapht/graph/AsWeightedGraph.java @@ -0,0 +1,147 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * AsWeightedGraph.java + * ---------------------- + * (C) Copyright 2007, by Lucas J. Scharenbroich and Contributors. + * + * Original Author: Lucas J. Scharenbroich + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 10-Sep-2007 : Initial revision (LJS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; + + +/** + *

    A weighted view of the backing graph specified in the constructor. This + * graph allows modules to apply algorithms designed for weighted graphs to an + * unweighted graph by providing an explicit edge weight mapping. The + * implementation also allows for "masking" weights for a subset of the edges in + * an existing weighted graph.

    + * + *

    Query operations on this graph "read through" to the backing graph. Vertex + * addition/removal and edge addition/removal are all supported (and immediately + * reflected in the backing graph). Setting an edge weight will pass the + * operation to the backing graph as well if the backing graph implements the + * WeightedGraph interface. Setting an edge weight will modify the weight map in + * order to maintain a consistent graph.

    + * + *

    Note that edges returned by this graph's accessors are really just the + * edges of the underlying directed graph.

    + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods. This graph will be serializable if the backing + * graph is serializable.

    + * + * @author Lucas J. Scharenbroich + * @since Sep 10, 2007 + */ +public class AsWeightedGraph + extends GraphDelegator + implements Serializable, + WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = -716810639338971372L; + + //~ Instance fields -------------------------------------------------------- + + protected final Map weightMap; + private final boolean isWeightedGraph; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for AsWeightedGraph. + * + * @param g the backing graph over which a weighted view is to be created. + * @param weightMap A mapping of edges to weights. If an edge is not present + * in the weight map, the edge weight for the underlying graph is returned. + * Note that a live reference to this map is retained, so if the caller + * changes the map after construction, the changes will affect the + * AsWeightedGraph instance as well. + */ + public AsWeightedGraph(Graph g, Map weightMap) + { + super(g); + assert (weightMap != null); + this.weightMap = weightMap; + + // Remember whether the backing graph implements the WeightedGraph + // interface + this.isWeightedGraph = (g instanceof WeightedGraph); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see WeightedGraph#setEdgeWeight + */ + public void setEdgeWeight(E e, double weight) + { + if (isWeightedGraph) { + super.setEdgeWeight(e, weight); + } + + // Always modify the weight map. It would be a terrible violation + // of the use contract to silently ignore changes to the weights. + weightMap.put(e, weight); + } + + /** + * @see Graph#getEdgeWeight + */ + public double getEdgeWeight(E e) + { + double weight; + + // Always return the value from the weight map first and + // only pass the call through as a backup + if (weightMap.containsKey(e)) { + weight = weightMap.get(e); + } else { + weight = super.getEdgeWeight(e); + } + + return weight; + } +} + +// End AsWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java b/wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java new file mode 100644 index 0000000..59a7dc9 --- /dev/null +++ b/wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java @@ -0,0 +1,91 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * ClassBasedEdgeFactory.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 04-Aug-2003 : Renamed from EdgeFactoryFactory & made utility class (BN); + * 03-Nov-2003 : Made edge factories serializable (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import org.jgrapht.*; + + +/** + * An {@link EdgeFactory} for producing edges by using a class as a factory. + * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public class ClassBasedEdgeFactory + implements EdgeFactory, + Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3618135658586388792L; + + //~ Instance fields -------------------------------------------------------- + + private final Class edgeClass; + + //~ Constructors ----------------------------------------------------------- + + public ClassBasedEdgeFactory(Class edgeClass) + { + this.edgeClass = edgeClass; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see EdgeFactory#createEdge(Object, Object) + */ + public E createEdge(V source, V target) + { + try { + return edgeClass.newInstance(); + } catch (Exception ex) { + throw new RuntimeException("Edge factory failed", ex); + } + } +} + +// End ClassBasedEdgeFactory.java diff --git a/wdl/org/jgrapht/graph/ClassBasedVertexFactory.java b/wdl/org/jgrapht/graph/ClassBasedVertexFactory.java new file mode 100644 index 0000000..8b2e5ff --- /dev/null +++ b/wdl/org/jgrapht/graph/ClassBasedVertexFactory.java @@ -0,0 +1,79 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * ClassBasedVertexFactory.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A {@link VertexFactory} for producing vertices by using a class as a factory. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class ClassBasedVertexFactory + implements VertexFactory +{ + //~ Instance fields -------------------------------------------------------- + + private final Class vertexClass; + + //~ Constructors ----------------------------------------------------------- + + public ClassBasedVertexFactory(Class vertexClass) + { + this.vertexClass = vertexClass; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see VertexFactory#createVertex() + */ + public V createVertex() + { + try { + return this.vertexClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException("Vertex factory failed", e); + } + } +} + +// End ClassBasedVertexFactory.java diff --git a/wdl/org/jgrapht/graph/DefaultDirectedGraph.java b/wdl/org/jgrapht/graph/DefaultDirectedGraph.java new file mode 100644 index 0000000..5f841a9 --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultDirectedGraph.java @@ -0,0 +1,86 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * DefaultDirectedGraph.java + * ------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed graph. A default directed graph is a non-simple directed graph in + * which multiple edges between any two vertices are not permitted, but + * loops are. + * + *

    prefixed 'Default' to avoid name collision with the DirectedGraph + * interface.

    + */ +public class DefaultDirectedGraph + extends AbstractBaseGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3544953246956466230L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new directed graph. + * + * @param edgeClass class on which to base factory for edges + */ + public DefaultDirectedGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new directed graph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public DefaultDirectedGraph(EdgeFactory ef) + { + super(ef, false, true); + } +} + +// End DefaultDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java b/wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java new file mode 100644 index 0000000..b069554 --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------------------- + * DefaultDirectedWeightedGraph.java + * --------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Jun-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed weighted graph. A directed weighted graph is a non-simple directed + * graph in which multiple edges between any two vertices are not + * permitted, but loops are. The graph has weights on its edges. + * + * @see DefaultDirectedGraph + */ +public class DefaultDirectedWeightedGraph + extends DefaultDirectedGraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3761405317841171513L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new directed weighted graph. + * + * @param edgeClass class on which to base factory for edges + */ + public DefaultDirectedWeightedGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new directed weighted graph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public DefaultDirectedWeightedGraph(EdgeFactory ef) + { + super(ef); + } +} + +// End DefaultDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultEdge.java b/wdl/org/jgrapht/graph/DefaultEdge.java new file mode 100644 index 0000000..1d7422c --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultEdge.java @@ -0,0 +1,91 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * DefaultEdge.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 10-Aug-2003 : General edge refactoring (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A default implementation for edges in a {@link Graph}. + * + * @author Barak Naveh + * @since Jul 14, 2003 + */ +public class DefaultEdge + extends IntrusiveEdge +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3258408452177932855L; + + //~ Methods ---------------------------------------------------------------- + + /** + * Retrieves the source of this edge. This is protected, for use by + * subclasses only (e.g. for implementing toString). + * + * @return source of this edge + */ + protected Object getSource() + { + return source; + } + + /** + * Retrieves the target of this edge. This is protected, for use by + * subclasses only (e.g. for implementing toString). + * + * @return target of this edge + */ + protected Object getTarget() + { + return target; + } + + public String toString() + { + return "(" + source + " : " + target + ")"; + } +} + +// End DefaultEdge.java diff --git a/wdl/org/jgrapht/graph/DefaultGraphMapping.java b/wdl/org/jgrapht/graph/DefaultGraphMapping.java new file mode 100644 index 0000000..8738906 --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultGraphMapping.java @@ -0,0 +1,135 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * DefaultGraphMapping.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Implementation of the GraphMapping interface. The performance of + * getVertex/EdgeCorrespondence is based on the performance of the + * concrete Map class which is passed in the constructor. For example, using + * hashmaps will provide O(1) performence. + * + * @author Assaf + * @since Jul 30, 2005 + */ +public class DefaultGraphMapping + implements GraphMapping +{ + //~ Instance fields -------------------------------------------------------- + + private Map graphMappingForward; + private Map graphMappingReverse; + + private Graph graph1; + private Graph graph2; + + //~ Constructors ----------------------------------------------------------- + + /** + * The maps themselves are used. There is no defensive-copy. Assumption: The + * key and value in the mappings are of valid graph objects. It is not + * checked. + * + * @param g1ToG2 + * @param g2ToG1 + * @param g1 + * @param g2 + */ + public DefaultGraphMapping( + Map g1ToG2, + Map g2ToG1, + Graph g1, + Graph g2) + { + this.graph1 = g1; + this.graph2 = g2; + this.graphMappingForward = g1ToG2; + this.graphMappingReverse = g2ToG1; + } + + //~ Methods ---------------------------------------------------------------- + + public E getEdgeCorrespondence(E currEdge, boolean forward) + { + Graph sourceGraph, targetGraph; + + if (forward) { + sourceGraph = this.graph1; + targetGraph = this.graph2; + } else { + sourceGraph = this.graph2; + targetGraph = this.graph1; + } + + V mappedSourceVertex = + getVertexCorrespondence( + sourceGraph.getEdgeSource(currEdge), + forward); + V mappedTargetVertex = + getVertexCorrespondence( + sourceGraph.getEdgeTarget(currEdge), + forward); + if ((mappedSourceVertex == null) || (mappedTargetVertex == null)) { + return null; + } else { + return targetGraph.getEdge( + mappedSourceVertex, + mappedTargetVertex); + } + } + + public V getVertexCorrespondence( + V keyVertex, + boolean forward) + { + Map graphMapping; + if (forward) { + graphMapping = graphMappingForward; + } else { + graphMapping = graphMappingReverse; + } + + return graphMapping.get(keyVertex); + } +} + +// End DefaultGraphMapping.java diff --git a/wdl/org/jgrapht/graph/DefaultListenableGraph.java b/wdl/org/jgrapht/graph/DefaultListenableGraph.java new file mode 100644 index 0000000..d131732 --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultListenableGraph.java @@ -0,0 +1,524 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------------- + * DefaultListenableGraph.java + * --------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 04-Aug-2003 : Strong refs to listeners instead of weak refs (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 07-Mar-2004 : Fixed unnecessary clone bug #819075 (BN); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; +import org.jgrapht.util.*; + + +/** + * A graph backed by the the graph specified at the constructor, which can be + * listened by GraphListener s and by + * VertexSetListener s. Operations on this graph "pass through" to the to + * the backing graph. Any modification made to this graph or the backing graph + * is reflected by the other. + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods.

    + * + * @author Barak Naveh + * @see GraphListener + * @see VertexSetListener + * @since Jul 20, 2003 + */ +public class DefaultListenableGraph + extends GraphDelegator + implements ListenableGraph, + Cloneable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3977575900898471984L; + + //~ Instance fields -------------------------------------------------------- + + private List> graphListeners = + new ArrayList>(); + private List> vertexSetListeners = + new ArrayList>(); + private FlyweightEdgeEvent reuseableEdgeEvent; + private FlyweightVertexEvent reuseableVertexEvent; + private boolean reuseEvents; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new listenable graph. + * + * @param g the backing graph. + */ + public DefaultListenableGraph(Graph g) + { + this(g, false); + } + + /** + * Creates a new listenable graph. If the reuseEvents flag is + * set to true this class will reuse previously fired events + * and will not create a new object for each event. This option increases + * performance but should be used with care, especially in multithreaded + * environment. + * + * @param g the backing graph. + * @param reuseEvents whether to reuse previously fired event objects + * instead of creating a new event object for each event. + * + * @throws IllegalArgumentException if the backing graph is already a + * listenable graph. + */ + public DefaultListenableGraph(Graph g, boolean reuseEvents) + { + super(g); + this.reuseEvents = reuseEvents; + reuseableEdgeEvent = new FlyweightEdgeEvent(this, -1, null); + reuseableVertexEvent = new FlyweightVertexEvent(this, -1, null); + + // the following restriction could be probably relaxed in the future. + if (g instanceof ListenableGraph) { + throw new IllegalArgumentException( + "base graph cannot be listenable"); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * If the reuseEvents flag is set to true this + * class will reuse previously fired events and will not create a new object + * for each event. This option increases performance but should be used with + * care, especially in multithreaded environment. + * + * @param reuseEvents whether to reuse previously fired event objects + * instead of creating a new event object for each event. + */ + public void setReuseEvents(boolean reuseEvents) + { + this.reuseEvents = reuseEvents; + } + + /** + * Tests whether the reuseEvents flag is set. If the flag is + * set to true this class will reuse previously fired events + * and will not create a new object for each event. This option increases + * performance but should be used with care, especially in multithreaded + * environment. + * + * @return the value of the reuseEvents flag. + */ + public boolean isReuseEvents() + { + return reuseEvents; + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + E e = super.addEdge(sourceVertex, targetVertex); + + if (e != null) { + fireEdgeAdded(e, sourceVertex, targetVertex); + } + + return e; + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + boolean added = super.addEdge(sourceVertex, targetVertex, e); + + if (added) { + fireEdgeAdded(e, sourceVertex, targetVertex); + } + + return added; + } + + /** + * @see ListenableGraph#addGraphListener(GraphListener) + */ + public void addGraphListener(GraphListener l) + { + addToListenerList(graphListeners, l); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + boolean modified = super.addVertex(v); + + if (modified) { + fireVertexAdded(v); + } + + return modified; + } + + /** + * @see ListenableGraph#addVertexSetListener(VertexSetListener) + */ + public void addVertexSetListener(VertexSetListener l) + { + addToListenerList(vertexSetListeners, l); + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() + { + try { + TypeUtil> typeDecl = null; + + DefaultListenableGraph g = + TypeUtil.uncheckedCast(super.clone(), typeDecl); + g.graphListeners = new ArrayList>(); + g.vertexSetListeners = new ArrayList>(); + + return g; + } catch (CloneNotSupportedException e) { + // should never get here since we're Cloneable + e.printStackTrace(); + throw new RuntimeException("internal error"); + } + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + E e = super.removeEdge(sourceVertex, targetVertex); + + if (e != null) { + fireEdgeRemoved(e, sourceVertex, targetVertex); + } + + return e; + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + V sourceVertex = getEdgeSource(e); + V targetVertex = getEdgeTarget(e); + + boolean modified = super.removeEdge(e); + + if (modified) { + fireEdgeRemoved(e, sourceVertex, targetVertex); + } + + return modified; + } + + /** + * @see ListenableGraph#removeGraphListener(GraphListener) + */ + public void removeGraphListener(GraphListener l) + { + graphListeners.remove(l); + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + if (containsVertex(v)) { + Set touchingEdgesList = edgesOf(v); + + // copy set to avoid ConcurrentModificationException + removeAllEdges(new ArrayList(touchingEdgesList)); + + super.removeVertex(v); // remove the vertex itself + + fireVertexRemoved(v); + + return true; + } else { + return false; + } + } + + /** + * @see ListenableGraph#removeVertexSetListener(VertexSetListener) + */ + public void removeVertexSetListener(VertexSetListener l) + { + vertexSetListeners.remove(l); + } + + /** + * Notify listeners that the specified edge was added. + * + * @param edge the edge that was added. + * + * @param source edge source + * + * @param target edge target + */ + protected void fireEdgeAdded(E edge, V source, V target) + { + GraphEdgeChangeEvent e = + createGraphEdgeChangeEvent( + GraphEdgeChangeEvent.EDGE_ADDED, + edge, source, target); + + for (GraphListener l : graphListeners) { + l.edgeAdded(e); + } + } + + /** + * Notify listeners that the specified edge was removed. + * + * @param edge the edge that was removed. + * + * @param source edge source + * + * @param target edge target + */ + protected void fireEdgeRemoved(E edge, V source, V target) + { + GraphEdgeChangeEvent e = + createGraphEdgeChangeEvent( + GraphEdgeChangeEvent.EDGE_REMOVED, + edge, source, target); + + for (GraphListener l : graphListeners) { + l.edgeRemoved(e); + } + } + + /** + * Notify listeners that the specified vertex was added. + * + * @param vertex the vertex that was added. + */ + protected void fireVertexAdded(V vertex) + { + GraphVertexChangeEvent e = + createGraphVertexChangeEvent( + GraphVertexChangeEvent.VERTEX_ADDED, + vertex); + + for (VertexSetListener l : vertexSetListeners) { + l.vertexAdded(e); + } + + for (GraphListener l : graphListeners) { + l.vertexAdded(e); + } + } + + /** + * Notify listeners that the specified vertex was removed. + * + * @param vertex the vertex that was removed. + */ + protected void fireVertexRemoved(V vertex) + { + GraphVertexChangeEvent e = + createGraphVertexChangeEvent( + GraphVertexChangeEvent.VERTEX_REMOVED, + vertex); + + for (VertexSetListener l : vertexSetListeners) { + l.vertexRemoved(e); + } + + for (GraphListener l : graphListeners) { + l.vertexRemoved(e); + } + } + + private static void addToListenerList( + List list, + L l) + { + if (!list.contains(l)) { + list.add(l); + } + } + + private GraphEdgeChangeEvent createGraphEdgeChangeEvent( + int eventType, E edge, V source, V target) + { + if (reuseEvents) { + reuseableEdgeEvent.setType(eventType); + reuseableEdgeEvent.setEdge(edge); + reuseableEdgeEvent.setEdgeSource(source); + reuseableEdgeEvent.setEdgeTarget(target); + + return reuseableEdgeEvent; + } else { + return new GraphEdgeChangeEvent( + this, eventType, edge, source, target); + } + } + + private GraphVertexChangeEvent createGraphVertexChangeEvent( + int eventType, + V vertex) + { + if (reuseEvents) { + reuseableVertexEvent.setType(eventType); + reuseableVertexEvent.setVertex(vertex); + + return reuseableVertexEvent; + } else { + return new GraphVertexChangeEvent(this, eventType, vertex); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * A reuseable edge event. + * + * @author Barak Naveh + * @since Aug 10, 2003 + */ + private static class FlyweightEdgeEvent + extends GraphEdgeChangeEvent + { + private static final long serialVersionUID = 3907207152526636089L; + + /** + * @see GraphEdgeChangeEvent#GraphEdgeChangeEvent(Object, int, Edge) + */ + public FlyweightEdgeEvent(Object eventSource, int type, EE e) + { + super(eventSource, type, e); + } + + /** + * Sets the edge of this event. + * + * @param e the edge to be set. + */ + protected void setEdge(EE e) + { + this.edge = e; + } + + protected void setEdgeSource(VV v) + { + this.edgeSource = v; + } + + protected void setEdgeTarget(VV v) + { + this.edgeTarget = v; + } + + /** + * Set the event type of this event. + * + * @param type the type to be set. + */ + protected void setType(int type) + { + this.type = type; + } + } + + /** + * A reuseable vertex event. + * + * @author Barak Naveh + * @since Aug 10, 2003 + */ + private static class FlyweightVertexEvent + extends GraphVertexChangeEvent + { + private static final long serialVersionUID = 3257848787857585716L; + + /** + * @see GraphVertexChangeEvent#GraphVertexChangeEvent(Object, int, + * Object) + */ + public FlyweightVertexEvent(Object eventSource, int type, VV vertex) + { + super(eventSource, type, vertex); + } + + /** + * Set the event type of this event. + * + * @param type type to be set. + */ + protected void setType(int type) + { + this.type = type; + } + + /** + * Sets the vertex of this event. + * + * @param vertex the vertex to be set. + */ + protected void setVertex(VV vertex) + { + this.vertex = vertex; + } + } +} + +// End DefaultListenableGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultWeightedEdge.java b/wdl/org/jgrapht/graph/DefaultWeightedEdge.java new file mode 100644 index 0000000..172fe9d --- /dev/null +++ b/wdl/org/jgrapht/graph/DefaultWeightedEdge.java @@ -0,0 +1,77 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * DefaultWeightedEdge.java + * ---------------- + * (C) Copyright 2006-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 29-May-2006 : Initial revision (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A default implementation for edges in a {@link WeightedGraph}. All access to + * the weight of an edge must go through the graph interface, which is why this + * class doesn't expose any public methods. + * + * @author John V. Sichi + */ +public class DefaultWeightedEdge + extends DefaultEdge +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 229708706467350994L; + + //~ Instance fields -------------------------------------------------------- + + double weight = WeightedGraph.DEFAULT_EDGE_WEIGHT; + + //~ Methods ---------------------------------------------------------------- + + /** + * Retrieves the weight of this edge. This is protected, for use by + * subclasses only (e.g. for implementing toString). + * + * @return weight of this edge + */ + protected double getWeight() + { + return weight; + } +} + +// End DefaultWeightedEdge.java diff --git a/wdl/org/jgrapht/graph/DirectedGraphUnion.java b/wdl/org/jgrapht/graph/DirectedGraphUnion.java new file mode 100644 index 0000000..b151370 --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedGraphUnion.java @@ -0,0 +1,109 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * DirectedGraphUnion.java + * ------------------------- + * (C) Copyright 2009-2009, by Ilya Razenshteyn + * + * Original Author: Ilya Razenshteyn and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 02-Feb-2009 : Initial revision (IR); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +public class DirectedGraphUnion + extends GraphUnion> + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -740199233080172450L; + + //~ Constructors ----------------------------------------------------------- + + public DirectedGraphUnion( + DirectedGraph g1, + DirectedGraph g2, + WeightCombiner operator) + { + super(g1, g2, operator); + } + + public DirectedGraphUnion(DirectedGraph g1, DirectedGraph g2) + { + super(g1, g2); + } + + //~ Methods ---------------------------------------------------------------- + + public int inDegreeOf(V vertex) + { + Set res = incomingEdgesOf(vertex); + return res.size(); + } + + public Set incomingEdgesOf(V vertex) + { + Set res = new HashSet(); + if (getG1().containsVertex(vertex)) { + res.addAll(getG1().incomingEdgesOf(vertex)); + } + if (getG2().containsVertex(vertex)) { + res.addAll(getG2().incomingEdgesOf(vertex)); + } + return Collections.unmodifiableSet(res); + } + + public int outDegreeOf(V vertex) + { + Set res = outgoingEdgesOf(vertex); + return res.size(); + } + + public Set outgoingEdgesOf(V vertex) + { + Set res = new HashSet(); + if (getG1().containsVertex(vertex)) { + res.addAll(getG1().outgoingEdgesOf(vertex)); + } + if (getG2().containsVertex(vertex)) { + res.addAll(getG2().outgoingEdgesOf(vertex)); + } + return Collections.unmodifiableSet(res); + } +} + +// End DirectedGraphUnion.java diff --git a/wdl/org/jgrapht/graph/DirectedMaskSubgraph.java b/wdl/org/jgrapht/graph/DirectedMaskSubgraph.java new file mode 100644 index 0000000..fdeaf32 --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedMaskSubgraph.java @@ -0,0 +1,64 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * DirectedMaskSubgraph.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed graph that is a {@link MaskSubgraph} on another graph. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class DirectedMaskSubgraph + extends MaskSubgraph + implements DirectedGraph +{ + //~ Constructors ----------------------------------------------------------- + + public DirectedMaskSubgraph( + DirectedGraph base, + MaskFunctor mask) + { + super(base, mask); + } +} + +// End DirectedMaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/DirectedMultigraph.java b/wdl/org/jgrapht/graph/DirectedMultigraph.java new file mode 100644 index 0000000..869674f --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedMultigraph.java @@ -0,0 +1,82 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------- + * DirectedMultigraph.java + * ----------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed multigraph. A directed multigraph is a non-simple directed graph + * in which loops and multiple edges between any two vertices are permitted. + */ +public class DirectedMultigraph + extends AbstractBaseGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3258408413590599219L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new directed multigraph. + * + * @param edgeClass class on which to base factory for edges + */ + public DirectedMultigraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new directed multigraph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public DirectedMultigraph(EdgeFactory ef) + { + super(ef, true, true); + } +} + +// End DirectedMultigraph.java diff --git a/wdl/org/jgrapht/graph/DirectedPseudograph.java b/wdl/org/jgrapht/graph/DirectedPseudograph.java new file mode 100644 index 0000000..6cf0be5 --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedPseudograph.java @@ -0,0 +1,80 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * DirectedPseudograph.java + * ---------------- + * (C) Copyright 2004-2008, by Christian Hammer and Contributors. + * + * Original Author: Christian Hammer + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 11-Mar-2004 : Initial revision: generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed pseudograph. A directed pseudograph is a non-simple directed graph + * in which both graph loops and multiple edges are permitted. If you're unsure + * about pseudographs, see: + * http://mathworld.wolfram.com/Pseudograph.html. + */ +public class DirectedPseudograph + extends AbstractBaseGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -8300409752893486415L; + + //~ Constructors ----------------------------------------------------------- + + /** + * @see AbstractBaseGraph + */ + public DirectedPseudograph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * @see AbstractBaseGraph + */ + public DirectedPseudograph(EdgeFactory ef) + { + super(ef, true, true); + } +} + +// End DirectedPseudograph.java diff --git a/wdl/org/jgrapht/graph/DirectedSubgraph.java b/wdl/org/jgrapht/graph/DirectedSubgraph.java new file mode 100644 index 0000000..5161135 --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedSubgraph.java @@ -0,0 +1,158 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------- + * DirectedSubgraph.java + * --------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * A directed graph that is a subgraph on other graph. + * + * @see Subgraph + */ +public class DirectedSubgraph + extends Subgraph> + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3616445700507054133L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new directed subgraph. + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + * @param edgeSubset edges to in include in the subgraph. If + * null then all the edges whose vertices found in the graph + * are included. + */ + public DirectedSubgraph( + DirectedGraph base, + Set vertexSubset, + Set edgeSubset) + { + super(base, vertexSubset, edgeSubset); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + assertVertexExist(vertex); + + int degree = 0; + + for (E e : getBase().incomingEdgesOf(vertex)) { + if (containsEdge(e)) { + degree++; + } + } + + return degree; + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + assertVertexExist(vertex); + + Set edges = new ArrayUnenforcedSet(); + + for (E e : getBase().incomingEdgesOf(vertex)) { + if (containsEdge(e)) { + edges.add(e); + } + } + + return edges; + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + assertVertexExist(vertex); + + int degree = 0; + + for (E e : getBase().outgoingEdgesOf(vertex)) { + if (containsEdge(e)) { + degree++; + } + } + + return degree; + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + assertVertexExist(vertex); + + Set edges = new ArrayUnenforcedSet(); + + for (E e : getBase().outgoingEdgesOf(vertex)) { + if (containsEdge(e)) { + edges.add(e); + } + } + + return edges; + } +} + +// End DirectedSubgraph.java diff --git a/wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java b/wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java new file mode 100644 index 0000000..06484ab --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java @@ -0,0 +1,84 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------- + * DirectedWeightedMultigraph.java + * ------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Jun-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed weighted multigraph. A directed weighted multigraph is a + * non-simple directed graph in which loops and multiple edges between any two + * vertices are permitted, and edges have weights. + */ +public class DirectedWeightedMultigraph + extends DirectedMultigraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 4049071636005206066L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new directed weighted multigraph. + * + * @param edgeClass class on which to base factory for edges + */ + public DirectedWeightedMultigraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new directed weighted multigraph with the specified edge + * factory. + * + * @param ef the edge factory of the new graph. + */ + public DirectedWeightedMultigraph(EdgeFactory ef) + { + super(ef); + } +} + +// End DirectedWeightedMultigraph.java diff --git a/wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java b/wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java new file mode 100644 index 0000000..8e852d5 --- /dev/null +++ b/wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java @@ -0,0 +1,83 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------------- + * DirectedWeightedSubgraph.java + * ----------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * A directed weighted graph that is a subgraph on other graph. + * + * @see Subgraph + */ +public class DirectedWeightedSubgraph + extends DirectedSubgraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3905799799168250680L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new weighted directed subgraph. + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + * @param edgeSubset edges to in include in the subgraph. If + * null then all the edges whose vertices found in the graph + * are included. + */ + public DirectedWeightedSubgraph( + WeightedGraph base, + Set vertexSubset, + Set edgeSubset) + { + super((DirectedGraph) base, vertexSubset, edgeSubset); + } +} + +// End DirectedWeightedSubgraph.java diff --git a/wdl/org/jgrapht/graph/EdgeReversedGraph.java b/wdl/org/jgrapht/graph/EdgeReversedGraph.java new file mode 100644 index 0000000..ab21b56 --- /dev/null +++ b/wdl/org/jgrapht/graph/EdgeReversedGraph.java @@ -0,0 +1,187 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------- + * EdgeReversedGraph.java + * ------------- + * (C) Copyright 2006-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 16-Sept-2006 : Initial revision (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * Provides an edge-reversed view g' of a directed graph g. The vertex sets for + * the two graphs are the same, but g' contains an edge (v2, v1) iff g contains + * an edge (v1, v2). g' is backed by g, so changes to g are reflected in g', and + * vice versa. + * + *

    This class allows you to use a directed graph algorithm in reverse. For + * example, suppose you have a directed graph representing a tree, with edges + * from parent to child, and you want to find all of the parents of a node. To + * do this, simply create an edge-reversed graph and pass that as input to + * {@link org.jgrapht.traverse.DepthFirstIterator}. + * + * @author John V. Sichi + * @see AsUndirectedGraph + */ +public class EdgeReversedGraph + extends GraphDelegator + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = 9091361782455418631L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new EdgeReversedGraph. + * + * @param g the base (backing) graph on which the edge-reversed view will be + * based. + */ + public EdgeReversedGraph(DirectedGraph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + return super.getEdge(targetVertex, sourceVertex); + } + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + return super.getAllEdges(targetVertex, sourceVertex); + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + return super.addEdge(targetVertex, sourceVertex); + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + return super.addEdge(targetVertex, sourceVertex, e); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + return super.outDegreeOf(vertex); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + return super.inDegreeOf(vertex); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + return super.outgoingEdgesOf(vertex); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + return super.incomingEdgesOf(vertex); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + return super.removeEdge(targetVertex, sourceVertex); + } + + /** + * @see Graph#getEdgeSource(Object) + */ + public V getEdgeSource(E e) + { + return super.getEdgeTarget(e); + } + + /** + * @see Graph#getEdgeTarget(Object) + */ + public V getEdgeTarget(E e) + { + return super.getEdgeSource(e); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() + { + return toStringFromSets( + vertexSet(), + edgeSet(), + true); + } +} + +// End EdgeReversedGraph.java diff --git a/wdl/org/jgrapht/graph/EdgeSetFactory.java b/wdl/org/jgrapht/graph/EdgeSetFactory.java new file mode 100644 index 0000000..828659c --- /dev/null +++ b/wdl/org/jgrapht/graph/EdgeSetFactory.java @@ -0,0 +1,73 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * EdgeSetFactory.java + * ---------------- + * (C) Copyright 2005-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 01-Jun-2005 : Initial revision (JVS); + * 06-Aug-2005 : Made generic (CH); + * 07-May-2006 : Renamed and changed from List to Set (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + + +/** + * A factory for edge sets. This interface allows the creator of a graph to + * choose the {@link java.util.Set} implementation used internally by the graph + * to maintain sets of edges. This provides control over performance tradeoffs + * between memory and CPU usage. + * + * @author John V. Sichi + */ +public interface EdgeSetFactory +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Create a new edge set for a particular vertex. + * + * @param vertex the vertex for which the edge set is being created; + * sophisticated factories may be able to use this information to choose an + * optimal set representation (e.g. ArrayUnenforcedSet for a vertex expected + * to have low degree, and LinkedHashSet for a vertex expected to have high + * degree) + * + * @return new set + */ + public Set createEdgeSet(V vertex); +} + +// End EdgeSetFactory.java diff --git a/wdl/org/jgrapht/graph/GraphDelegator.java b/wdl/org/jgrapht/graph/GraphDelegator.java new file mode 100644 index 0000000..1f4e6dc --- /dev/null +++ b/wdl/org/jgrapht/graph/GraphDelegator.java @@ -0,0 +1,298 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * GraphDelegator.java + * ------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * A graph backed by the the graph specified at the constructor, which delegates + * all its methods to the backing graph. Operations on this graph "pass through" + * to the to the backing graph. Any modification made to this graph or the + * backing graph is reflected by the other. + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods.

    + * + *

    This class is mostly used as a base for extending subclasses.

    + * + * @author Barak Naveh + * @since Jul 20, 2003 + */ +public class GraphDelegator + extends AbstractGraph + implements Graph, + Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3257005445226181425L; + + //~ Instance fields -------------------------------------------------------- + + /** + * The graph to which operations are delegated. + */ + private Graph delegate; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructor for GraphDelegator. + * + * @param g the backing graph (the delegate). + * + * @throws IllegalArgumentException iff g==null + */ + public GraphDelegator(Graph g) + { + super(); + + if (g == null) { + throw new IllegalArgumentException("g must not be null."); + } + + delegate = g; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + return delegate.getAllEdges(sourceVertex, targetVertex); + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + return delegate.getEdge(sourceVertex, targetVertex); + } + + /** + * @see Graph#getEdgeFactory() + */ + public EdgeFactory getEdgeFactory() + { + return delegate.getEdgeFactory(); + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + return delegate.addEdge(sourceVertex, targetVertex); + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + return delegate.addEdge(sourceVertex, targetVertex, e); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + return delegate.addVertex(v); + } + + /** + * @see Graph#containsEdge(Object) + */ + public boolean containsEdge(E e) + { + return delegate.containsEdge(e); + } + + /** + * @see Graph#containsVertex(Object) + */ + public boolean containsVertex(V v) + { + return delegate.containsVertex(v); + } + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + return ((UndirectedGraph) delegate).degreeOf(vertex); + } + + /** + * @see Graph#edgeSet() + */ + public Set edgeSet() + { + return delegate.edgeSet(); + } + + /** + * @see Graph#edgesOf(Object) + */ + public Set edgesOf(V vertex) + { + return delegate.edgesOf(vertex); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + return ((DirectedGraph) delegate).inDegreeOf(vertex); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + return ((DirectedGraph) delegate).incomingEdgesOf(vertex); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + return ((DirectedGraph) delegate).outDegreeOf(vertex); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + return ((DirectedGraph) delegate).outgoingEdgesOf(vertex); + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + return delegate.removeEdge(e); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + return delegate.removeEdge(sourceVertex, targetVertex); + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + return delegate.removeVertex(v); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() + { + return delegate.toString(); + } + + /** + * @see Graph#vertexSet() + */ + public Set vertexSet() + { + return delegate.vertexSet(); + } + + /** + * @see Graph#getEdgeSource(Object) + */ + public V getEdgeSource(E e) + { + return delegate.getEdgeSource(e); + } + + /** + * @see Graph#getEdgeTarget(Object) + */ + public V getEdgeTarget(E e) + { + return delegate.getEdgeTarget(e); + } + + /** + * @see Graph#getEdgeWeight(Object) + */ + public double getEdgeWeight(E e) + { + return delegate.getEdgeWeight(e); + } + + /** + * @see WeightedGraph#setEdgeWeight(Object, double) + */ + public void setEdgeWeight(E e, double weight) + { + ((WeightedGraph) delegate).setEdgeWeight(e, weight); + } +} + +// End GraphDelegator.java diff --git a/wdl/org/jgrapht/graph/GraphPathImpl.java b/wdl/org/jgrapht/graph/GraphPathImpl.java new file mode 100644 index 0000000..b2e3b91 --- /dev/null +++ b/wdl/org/jgrapht/graph/GraphPathImpl.java @@ -0,0 +1,122 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * GraphPathImpl.java + * ---------------- + * (C) Copyright 2009-2009, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 03-Jul-2009 : Initial revision (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * GraphPathImpl is a default implementation of {@link GraphPath}. + * + * @author John Sichi + * @version $Id$ + */ +public class GraphPathImpl + implements GraphPath +{ + //~ Instance fields -------------------------------------------------------- + + private Graph graph; + + private List edgeList; + + private V startVertex; + + private V endVertex; + + private double weight; + + //~ Constructors ----------------------------------------------------------- + + public GraphPathImpl( + Graph graph, + V startVertex, + V endVertex, + List edgeList, + double weight) + { + this.graph = graph; + this.startVertex = startVertex; + this.endVertex = endVertex; + this.edgeList = edgeList; + this.weight = weight; + } + + //~ Methods ---------------------------------------------------------------- + + // implement GraphPath + public Graph getGraph() + { + return graph; + } + + // implement GraphPath + public V getStartVertex() + { + return startVertex; + } + + // implement GraphPath + public V getEndVertex() + { + return endVertex; + } + + // implement GraphPath + public List getEdgeList() + { + return edgeList; + } + + // implement GraphPath + public double getWeight() + { + return weight; + } + + // override Object + public String toString() + { + return edgeList.toString(); + } +} + +// End GraphPathImpl.java diff --git a/wdl/org/jgrapht/graph/GraphUnion.java b/wdl/org/jgrapht/graph/GraphUnion.java new file mode 100644 index 0000000..6659c07 --- /dev/null +++ b/wdl/org/jgrapht/graph/GraphUnion.java @@ -0,0 +1,288 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * GraphUnion.java + * ------------------------- + * (C) Copyright 2009-2009, by Ilya Razenshteyn + * + * Original Author: Ilya Razenshteyn and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 02-Feb-2009 : Initial revision (IR); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + *

    Read-only union of two graphs: G1 and G2. If + * G1 = (V1, E1) and G2 = + * (V2, E2) then their union G = (V, E), where V is the + * union of V1 and V2, and E is the union of E1 + * and E1.

    + * + *

    GraphUnion implements Graph interface. + * GraphUnion uses WeightCombiner to choose policy for calculating + * edge weight.

    + */ +public class GraphUnion> + extends AbstractGraph + implements Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -740199233080172450L; + + private static final String READ_ONLY = "union of graphs is read-only"; + + //~ Instance fields -------------------------------------------------------- + + private G g1; + private G g2; + private WeightCombiner operator; + + //~ Constructors ----------------------------------------------------------- + + public GraphUnion(G g1, G g2, WeightCombiner operator) + { + if (g1 == null) { + throw new NullPointerException("g1 is null"); + } + if (g2 == null) { + throw new NullPointerException("g2 is null"); + } + if (g1 == g2) { + throw new IllegalArgumentException("g1 is equal to g2"); + } + this.g1 = g1; + this.g2 = g2; + this.operator = operator; + } + + public GraphUnion(G g1, G g2) + { + this(g1, g2, WeightCombiner.SUM); + } + + //~ Methods ---------------------------------------------------------------- + + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set res = new HashSet(); + if (g1.containsVertex(sourceVertex) + && g1.containsVertex(targetVertex)) + { + res.addAll(g1.getAllEdges(sourceVertex, targetVertex)); + } + if (g2.containsVertex(sourceVertex) + && g2.containsVertex(targetVertex)) + { + res.addAll(g2.getAllEdges(sourceVertex, targetVertex)); + } + return Collections.unmodifiableSet(res); + } + + public E getEdge(V sourceVertex, V targetVertex) + { + E res = null; + if (g1.containsVertex(sourceVertex) + && g1.containsVertex(targetVertex)) + { + res = g1.getEdge(sourceVertex, targetVertex); + } + if ((res == null) + && g2.containsVertex(sourceVertex) + && g2.containsVertex(targetVertex)) + { + res = g2.getEdge(sourceVertex, targetVertex); + } + return res; + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public EdgeFactory getEdgeFactory() + { + throw new UnsupportedOperationException(READ_ONLY); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public E addEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public boolean addVertex(V v) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + public boolean containsEdge(E e) + { + return g1.containsEdge(e) || g2.containsEdge(e); + } + + public boolean containsVertex(V v) + { + return g1.containsVertex(v) || g2.containsVertex(v); + } + + public Set edgeSet() + { + Set res = new HashSet(); + res.addAll(g1.edgeSet()); + res.addAll(g2.edgeSet()); + return Collections.unmodifiableSet(res); + } + + public Set edgesOf(V vertex) + { + Set res = new HashSet(); + if (g1.containsVertex(vertex)) { + res.addAll(g1.edgesOf(vertex)); + } + if (g2.containsVertex(vertex)) { + res.addAll(g2.edgesOf(vertex)); + } + return Collections.unmodifiableSet(res); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public boolean removeEdge(E e) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + /** + * Throws UnsupportedOperationException, because + * GraphUnion is read-only. + */ + public boolean removeVertex(V v) + { + throw new UnsupportedOperationException(READ_ONLY); + } + + public Set vertexSet() + { + Set res = new HashSet(); + res.addAll(g1.vertexSet()); + res.addAll(g2.vertexSet()); + return Collections.unmodifiableSet(res); + } + + public V getEdgeSource(E e) + { + if (g1.containsEdge(e)) { + return g1.getEdgeSource(e); + } + if (g2.containsEdge(e)) { + return g2.getEdgeSource(e); + } + return null; + } + + public V getEdgeTarget(E e) + { + if (g1.containsEdge(e)) { + return g1.getEdgeTarget(e); + } + if (g2.containsEdge(e)) { + return g2.getEdgeTarget(e); + } + return null; + } + + public double getEdgeWeight(E e) + { + if (g1.containsEdge(e) && g2.containsEdge(e)) { + return operator.combine(g1.getEdgeWeight(e), g2.getEdgeWeight(e)); + } + if (g1.containsEdge(e)) { + return g1.getEdgeWeight(e); + } + if (g2.containsEdge(e)) { + return g2.getEdgeWeight(e); + } + throw new IllegalArgumentException("no such edge in the union"); + } + + /** + * @return G1 + */ + public G getG1() + { + return g1; + } + + /** + * @return G2 + */ + public G getG2() + { + return g2; + } +} + +// End GraphUnion.java diff --git a/wdl/org/jgrapht/graph/IntrusiveEdge.java b/wdl/org/jgrapht/graph/IntrusiveEdge.java new file mode 100644 index 0000000..bc7aa36 --- /dev/null +++ b/wdl/org/jgrapht/graph/IntrusiveEdge.java @@ -0,0 +1,82 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * IntrusiveEdge.java + * ------------------- + * (C) Copyright 2006-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 28-May-2006 : Initial revision (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + + +/** + * IntrusiveEdge encapsulates the internals for the default edge implementation. + * It is not intended to be referenced directly (which is why it's not public); + * use DefaultEdge for that. + * + * @author John V. Sichi + */ +class IntrusiveEdge + implements Cloneable, + Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3258408452177932855L; + + //~ Instance fields -------------------------------------------------------- + + Object source; + + Object target; + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Object#clone() + */ + public Object clone() + { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // shouldn't happen as we are Cloneable + throw new InternalError(); + } + } +} + +// End IntrusiveEdge.java diff --git a/wdl/org/jgrapht/graph/ListenableDirectedGraph.java b/wdl/org/jgrapht/graph/ListenableDirectedGraph.java new file mode 100644 index 0000000..7b96449 --- /dev/null +++ b/wdl/org/jgrapht/graph/ListenableDirectedGraph.java @@ -0,0 +1,83 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------------- + * ListenableDirectedGraph.java + * ---------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed graph which is also {@link org.jgrapht.ListenableGraph}. + * + * @see DefaultListenableGraph + */ +public class ListenableDirectedGraph + extends DefaultListenableGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3257571698126368824L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new listenable directed graph. + * + * @param edgeClass class on which to base factory for edges + */ + public ListenableDirectedGraph(Class edgeClass) + { + this(new DefaultDirectedGraph(edgeClass)); + } + + /** + * Creates a new listenable directed graph. + * + * @param base the backing graph. + */ + public ListenableDirectedGraph(DirectedGraph base) + { + super(base); + } +} + +// End ListenableDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java b/wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java new file mode 100644 index 0000000..eaff740 --- /dev/null +++ b/wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java @@ -0,0 +1,84 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------------ + * ListenableDirectedWeightedGraph.java + * ------------------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id: ListenableDirectedWeightedGraph.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Jun-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed weighted graph which is also {@link org.jgrapht.ListenableGraph}. + * + * @see DefaultListenableGraph + */ +public class ListenableDirectedWeightedGraph + extends ListenableDirectedGraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3977582476627621938L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new listenable directed weighted graph. + * + * @param edgeClass class on which to base factory for edges + */ + public ListenableDirectedWeightedGraph(Class edgeClass) + { + this(new DefaultDirectedWeightedGraph(edgeClass)); + } + + /** + * Creates a new listenable directed weighted graph. + * + * @param base the backing graph. + */ + public ListenableDirectedWeightedGraph(WeightedGraph base) + { + super((DirectedGraph) base); + } +} + +// End ListenableDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableUndirectedGraph.java b/wdl/org/jgrapht/graph/ListenableUndirectedGraph.java new file mode 100644 index 0000000..3f44b50 --- /dev/null +++ b/wdl/org/jgrapht/graph/ListenableUndirectedGraph.java @@ -0,0 +1,83 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------ + * ListenableUndirectedGraph.java + * ------------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * An undirected graph which is also {@link org.jgrapht.ListenableGraph}. + * + * @see DefaultListenableGraph + */ +public class ListenableUndirectedGraph + extends DefaultListenableGraph + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3256999969193145905L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new listenable undirected simple graph. + * + * @param edgeClass class on which to base factory for edges + */ + public ListenableUndirectedGraph(Class edgeClass) + { + this(new SimpleGraph(edgeClass)); + } + + /** + * Creates a new listenable undirected graph. + * + * @param base the backing graph. + */ + public ListenableUndirectedGraph(UndirectedGraph base) + { + super(base); + } +} + +// End ListenableUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java b/wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java new file mode 100644 index 0000000..1910c50 --- /dev/null +++ b/wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------------------- + * ListenableUndirectedWeightedGraph.java + * -------------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id: ListenableUndirectedWeightedGraph.java 485 2006-06-26 09:12:14Z + * perfecthash $ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Jun-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * An undirected weighted graph which is also {@link + * org.jgrapht.ListenableGraph}. + * + * @see DefaultListenableGraph + */ +public class ListenableUndirectedWeightedGraph + extends ListenableUndirectedGraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3690762799613949747L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new listenable undirected weighted graph. + * + * @param edgeClass class on which to base factory for edges + */ + public ListenableUndirectedWeightedGraph(Class edgeClass) + { + this(new SimpleWeightedGraph(edgeClass)); + } + + /** + * Creates a new listenable undirected weighted graph. + * + * @param base the backing graph. + */ + public ListenableUndirectedWeightedGraph(WeightedGraph base) + { + super((UndirectedGraph) base); + } +} + +// End ListenableUndirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/MaskEdgeSet.java b/wdl/org/jgrapht/graph/MaskEdgeSet.java new file mode 100644 index 0000000..234ad37 --- /dev/null +++ b/wdl/org/jgrapht/graph/MaskEdgeSet.java @@ -0,0 +1,149 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * MaskEdgeSet.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; +import org.jgrapht.util.PrefetchIterator.*; + + +/** + * Helper for {@link MaskSubgraph}. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +class MaskEdgeSet + extends AbstractSet +{ + //~ Instance fields -------------------------------------------------------- + + private Set edgeSet; + + private Graph graph; + + private MaskFunctor mask; + + private transient TypeUtil edgeTypeDecl = null; + + private int size; + + //~ Constructors ----------------------------------------------------------- + + public MaskEdgeSet( + Graph graph, + Set edgeSet, + MaskFunctor mask) + { + this.graph = graph; + this.edgeSet = edgeSet; + this.mask = mask; + this.size = -1; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see java.util.Collection#contains(java.lang.Object) + */ + public boolean contains(Object o) + { + return this.edgeSet.contains(o) + && !this.mask.isEdgeMasked(TypeUtil.uncheckedCast(o, edgeTypeDecl)); + } + + /** + * @see java.util.Set#iterator() + */ + public Iterator iterator() + { + return new PrefetchIterator(new MaskEdgeSetNextElementFunctor()); + } + + /** + * @see java.util.Set#size() + */ + public int size() + { + if (this.size == -1) { + this.size = 0; + for (Iterator iter = iterator(); iter.hasNext();) { + iter.next(); + this.size++; + } + } + return this.size; + } + + //~ Inner Classes ---------------------------------------------------------- + + private class MaskEdgeSetNextElementFunctor + implements NextElementFunctor + { + private Iterator iter; + + public MaskEdgeSetNextElementFunctor() + { + this.iter = MaskEdgeSet.this.edgeSet.iterator(); + } + + public E nextElement() + throws NoSuchElementException + { + E edge = this.iter.next(); + while (isMasked(edge)) { + edge = this.iter.next(); + } + return edge; + } + + private boolean isMasked(E edge) + { + return MaskEdgeSet.this.mask.isEdgeMasked(edge) + || MaskEdgeSet.this.mask.isVertexMasked( + MaskEdgeSet.this.graph.getEdgeSource(edge)) + || MaskEdgeSet.this.mask.isVertexMasked( + MaskEdgeSet.this.graph.getEdgeTarget(edge)); + } + } +} + +// End MaskEdgeSet.java diff --git a/wdl/org/jgrapht/graph/MaskFunctor.java b/wdl/org/jgrapht/graph/MaskFunctor.java new file mode 100644 index 0000000..a16547a --- /dev/null +++ b/wdl/org/jgrapht/graph/MaskFunctor.java @@ -0,0 +1,72 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * MaskFunctor.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +/** + * A functor interface for masking out vertices and edges of a graph. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public interface MaskFunctor +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Returns true if the edge is masked, false + * otherwise. + * + * @param edge edge. + * + * @return . + */ + public boolean isEdgeMasked(E edge); + + /** + * Returns true if the vertex is masked, false + * otherwise. + * + * @param vertex vertex. + * + * @return . + */ + public boolean isVertexMasked(V vertex); +} + +// End MaskFunctor.java diff --git a/wdl/org/jgrapht/graph/MaskSubgraph.java b/wdl/org/jgrapht/graph/MaskSubgraph.java new file mode 100644 index 0000000..18951f5 --- /dev/null +++ b/wdl/org/jgrapht/graph/MaskSubgraph.java @@ -0,0 +1,298 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * MaskSubgraph.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * An unmodifiable subgraph induced by a vertex/edge masking function. The + * subgraph will keep track of edges being added to its vertex subset as well as + * deletion of edges and vertices. When iterating over the vertices/edges, it + * will iterate over the vertices/edges of the base graph and discard + * vertices/edges that are masked (an edge with a masked extremity vertex is + * discarded as well). + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class MaskSubgraph + extends AbstractGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final String UNMODIFIABLE = "this graph is unmodifiable"; + + //~ Instance fields -------------------------------------------------------- + + private Graph base; + + private Set edges; + + private MaskFunctor mask; + + private Set vertices; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new induced subgraph. Running-time = O(1). + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param mask vertices and edges to exclude in the subgraph. If a + * vertex/edge is masked, it is as if it is not in the subgraph. + */ + public MaskSubgraph(Graph base, MaskFunctor mask) + { + super(); + this.base = base; + this.mask = mask; + + this.vertices = new MaskVertexSet(base.vertexSet(), mask); + this.edges = new MaskEdgeSet(base, base.edgeSet(), mask); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + public boolean addEdge(V sourceVertex, V targetVertex, E edge) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + public boolean containsEdge(E e) + { + return edgeSet().contains(e); + } + + public boolean containsVertex(V v) + { + return !this.mask.isVertexMasked(v) && this.base.containsVertex(v); + } + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + return edgesOf(vertex).size(); + } + + public Set edgeSet() + { + return this.edges; + } + + public Set edgesOf(V vertex) + { + assertVertexExist(vertex); + + return new MaskEdgeSet( + this.base, + this.base.edgesOf(vertex), + this.mask); + } + + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (containsVertex(sourceVertex) && containsVertex(targetVertex)) { + return new MaskEdgeSet( + this.base, + this.base.getAllEdges( + sourceVertex, + targetVertex), + this.mask); + } + + return edges; + } + + public E getEdge(V sourceVertex, V targetVertex) + { + Set edges = getAllEdges(sourceVertex, targetVertex); + + if ((edges == null) || edges.isEmpty()) { + return null; + } else { + return edges.iterator().next(); + } + } + + public EdgeFactory getEdgeFactory() + { + return this.base.getEdgeFactory(); + } + + public V getEdgeSource(E edge) + { + assert (edgeSet().contains(edge)); + + return this.base.getEdgeSource(edge); + } + + public V getEdgeTarget(E edge) + { + assert (edgeSet().contains(edge)); + + return this.base.getEdgeTarget(edge); + } + + public double getEdgeWeight(E edge) + { + assert (edgeSet().contains(edge)); + + return this.base.getEdgeWeight(edge); + } + + /** + * @see DirectedGraph#incomingEdgesOf(Object) + */ + public Set incomingEdgesOf(V vertex) + { + assertVertexExist(vertex); + + return new MaskEdgeSet( + this.base, + ((DirectedGraph) this.base).incomingEdgesOf(vertex), + this.mask); + } + + /** + * @see DirectedGraph#inDegreeOf(Object) + */ + public int inDegreeOf(V vertex) + { + return incomingEdgesOf(vertex).size(); + } + + /** + * @see DirectedGraph#outDegreeOf(Object) + */ + public int outDegreeOf(V vertex) + { + return outgoingEdgesOf(vertex).size(); + } + + /** + * @see DirectedGraph#outgoingEdgesOf(Object) + */ + public Set outgoingEdgesOf(V vertex) + { + assertVertexExist(vertex); + + return new MaskEdgeSet( + this.base, + ((DirectedGraph) this.base).outgoingEdgesOf(vertex), + this.mask); + } + + /** + * @see Graph#removeAllEdges(Collection) + */ + public boolean removeAllEdges(Collection edges) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllEdges(Object, Object) + */ + public Set removeAllEdges(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllVertices(Collection) + */ + public boolean removeAllVertices(Collection vertices) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + public Set vertexSet() + { + return this.vertices; + } +} + +// End MaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/MaskVertexSet.java b/wdl/org/jgrapht/graph/MaskVertexSet.java new file mode 100644 index 0000000..5daf256 --- /dev/null +++ b/wdl/org/jgrapht/graph/MaskVertexSet.java @@ -0,0 +1,134 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * MaskVertexSet.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.util.*; +import org.jgrapht.util.PrefetchIterator.*; + + +/** + * Helper for {@link MaskSubgraph}. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +class MaskVertexSet + extends AbstractSet +{ + //~ Instance fields -------------------------------------------------------- + + private MaskFunctor mask; + + private int size; + + private Set vertexSet; + + private transient TypeUtil vertexTypeDecl = null; + + //~ Constructors ----------------------------------------------------------- + + public MaskVertexSet(Set vertexSet, MaskFunctor mask) + { + this.vertexSet = vertexSet; + this.mask = mask; + this.size = -1; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see java.util.Collection#contains(java.lang.Object) + */ + public boolean contains(Object o) + { + return + !this.mask.isVertexMasked(TypeUtil.uncheckedCast(o, vertexTypeDecl)) + && this.vertexSet.contains(o); + } + + /** + * @see java.util.Set#iterator() + */ + public Iterator iterator() + { + return new PrefetchIterator(new MaskVertexSetNextElementFunctor()); + } + + /** + * @see java.util.Set#size() + */ + public int size() + { + if (this.size == -1) { + this.size = 0; + for (Iterator iter = iterator(); iter.hasNext();) { + iter.next(); + this.size++; + } + } + return this.size; + } + + //~ Inner Classes ---------------------------------------------------------- + + private class MaskVertexSetNextElementFunctor + implements NextElementFunctor + { + private Iterator iter; + + public MaskVertexSetNextElementFunctor() + { + this.iter = MaskVertexSet.this.vertexSet.iterator(); + } + + public V nextElement() + throws NoSuchElementException + { + V element = this.iter.next(); + while (MaskVertexSet.this.mask.isVertexMasked(element)) { + element = this.iter.next(); + } + return element; + } + } +} + +// End MaskVertexSet.java diff --git a/wdl/org/jgrapht/graph/Multigraph.java b/wdl/org/jgrapht/graph/Multigraph.java new file mode 100644 index 0000000..5a9150f --- /dev/null +++ b/wdl/org/jgrapht/graph/Multigraph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------- + * Multigraph.java + * --------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A multigraph. A multigraph is a non-simple undirected graph in which no loops + * are permitted, but multiple edges between any two vertices are. If you're + * unsure about multigraphs, see: + * http://mathworld.wolfram.com/Multigraph.html. + */ +public class Multigraph + extends AbstractBaseGraph + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3257001055819871795L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new multigraph. + * + * @param edgeClass class on which to base factory for edges + */ + public Multigraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new multigraph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public Multigraph(EdgeFactory ef) + { + super(ef, true, false); + } +} + +// End Multigraph.java diff --git a/wdl/org/jgrapht/graph/ParanoidGraph.java b/wdl/org/jgrapht/graph/ParanoidGraph.java new file mode 100644 index 0000000..9b6983a --- /dev/null +++ b/wdl/org/jgrapht/graph/ParanoidGraph.java @@ -0,0 +1,110 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------- + * ParanoidGraph.java + * ------------------- + * (C) Copyright 2007-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 8-Nov-2007 : Initial revision (JVS); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * ParanoidGraph provides a way to verify that objects added to a graph obey the + * standard equals/hashCode contract. It can be used to wrap an underlying graph + * to be verified. Note that the verification is very expensive, so + * ParanoidGraph should only be used during debugging. + * + * @author John Sichi + * @version $Id$ + */ +public class ParanoidGraph + extends GraphDelegator +{ + //~ Static fields/initializers --------------------------------------------- + + /** + */ + private static final long serialVersionUID = 5075284167422166539L; + + //~ Constructors ----------------------------------------------------------- + + public ParanoidGraph(Graph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + verifyAdd(edgeSet(), e); + return super.addEdge(sourceVertex, targetVertex, e); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + verifyAdd(vertexSet(), v); + return super.addVertex(v); + } + + private static void verifyAdd(Set set, T t) + { + for (T o : set) { + if (o == t) { + continue; + } + if (o.equals(t) && (o.hashCode() != t.hashCode())) { + throw new IllegalArgumentException( + "ParanoidGraph detected objects " + + "o1 (hashCode=" + o.hashCode() + + ") and o2 (hashCode=" + t.hashCode() + + ") where o1.equals(o2) " + + "but o1.hashCode() != o2.hashCode()"); + } + } + } +} + +// End ParanoidGraph.java diff --git a/wdl/org/jgrapht/graph/Pseudograph.java b/wdl/org/jgrapht/graph/Pseudograph.java new file mode 100644 index 0000000..1b4ac16 --- /dev/null +++ b/wdl/org/jgrapht/graph/Pseudograph.java @@ -0,0 +1,84 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * Pseudograph.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A pseudograph. A pseudograph is a non-simple undirected graph in which both + * graph loops and multiple edges are permitted. If you're unsure about + * pseudographs, see: + * http://mathworld.wolfram.com/Pseudograph.html. + */ +public class Pseudograph + extends AbstractBaseGraph + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3833183614484755253L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new pseudograph. + * + * @param edgeClass class on which to base factory for edges + */ + public Pseudograph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new pseudograph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public Pseudograph(EdgeFactory ef) + { + super(ef, true, true); + } +} + +// End Pseudograph.java diff --git a/wdl/org/jgrapht/graph/SimpleDirectedGraph.java b/wdl/org/jgrapht/graph/SimpleDirectedGraph.java new file mode 100644 index 0000000..115c7bd --- /dev/null +++ b/wdl/org/jgrapht/graph/SimpleDirectedGraph.java @@ -0,0 +1,82 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------ + * SimpleDirectedGraph.java + * ------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A simple directed graph. A simple directed graph is a directed graph in which + * neither multiple edges between any two vertices nor loops are permitted. + */ +public class SimpleDirectedGraph + extends AbstractBaseGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 4049358608472879671L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new simple directed graph. + * + * @param edgeClass class on which to base factory for edges + */ + public SimpleDirectedGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } + + /** + * Creates a new simple directed graph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public SimpleDirectedGraph(EdgeFactory ef) + { + super(ef, false, false); + } +} + +// End SimpleDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java b/wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java new file mode 100644 index 0000000..089b781 --- /dev/null +++ b/wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java @@ -0,0 +1,83 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------------- + * SimpleDirectedWeightedGraph.java + * -------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A simple directed weighted graph. A simple directed weighted graph is a + * simple directed graph for which edges are assigned weights. + */ +public class SimpleDirectedWeightedGraph + extends SimpleDirectedGraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3904960841681220919L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new simple directed weighted graph with the specified edge + * factory. + * + * @param ef the edge factory of the new graph. + */ + public SimpleDirectedWeightedGraph(EdgeFactory ef) + { + super(ef); + } + + /** + * Creates a new simple directed weighted graph. + * + * @param edgeClass class on which to base factory for edges + */ + public SimpleDirectedWeightedGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } +} + +// End SimpleDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleGraph.java b/wdl/org/jgrapht/graph/SimpleGraph.java new file mode 100644 index 0000000..50e88e7 --- /dev/null +++ b/wdl/org/jgrapht/graph/SimpleGraph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------- + * SimpleGraph.java + * ---------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): CHristian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A simple graph. A simple graph is an undirected graph for which at most one + * edge connects any two vertices, and loops are not permitted. If you're unsure + * about simple graphs, see: + * http://mathworld.wolfram.com/SimpleGraph.html. + */ +public class SimpleGraph + extends AbstractBaseGraph + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3545796589454112304L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new simple graph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public SimpleGraph(EdgeFactory ef) + { + super(ef, false, false); + } + + /** + * Creates a new simple graph. + * + * @param edgeClass class on which to base factory for edges + */ + public SimpleGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } +} + +// End SimpleGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleWeightedGraph.java b/wdl/org/jgrapht/graph/SimpleWeightedGraph.java new file mode 100644 index 0000000..1d2f3f0 --- /dev/null +++ b/wdl/org/jgrapht/graph/SimpleWeightedGraph.java @@ -0,0 +1,82 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------ + * SimpleWeightedGraph.java + * ------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A simple weighted graph. A simple weighted graph is a simple graph for which + * edges are assigned weights. + */ +public class SimpleWeightedGraph + extends SimpleGraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3906088949100655922L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new simple weighted graph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public SimpleWeightedGraph(EdgeFactory ef) + { + super(ef); + } + + /** + * Creates a new simple weighted graph. + * + * @param edgeClass class on which to base factory for edges + */ + public SimpleWeightedGraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } +} + +// End SimpleWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/Subgraph.java b/wdl/org/jgrapht/graph/Subgraph.java new file mode 100644 index 0000000..bfb7da5 --- /dev/null +++ b/wdl/org/jgrapht/graph/Subgraph.java @@ -0,0 +1,546 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------- + * Subgraph.java + * ------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 26-Jul-2003 : Accurate constructors to avoid casting problems (BN); + * 10-Aug-2003 : Adaptation to new event model (BN); + * 23-Oct-2003 : Allowed non-listenable graph as base (BN); + * 07-Feb-2004 : Enabled serialization (BN); + * 11-Mar-2004 : Made generic (CH); + * 15-Mar-2004 : Integrity is now checked using Maps (CH); + * 20-Mar-2004 : Cancelled verification of element identity to base graph (BN); + * 21-Sep-2004 : Added induced subgraph (who?) + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; +import org.jgrapht.util.*; + + +/** + * A subgraph is a graph that has a subset of vertices and a subset of edges + * with respect to some base graph. More formally, a subgraph G(V,E) that is + * based on a base graph Gb(Vb,Eb) satisfies the following subgraph + * property: V is a subset of Vb and E is a subset of Eb. Other than + * this property, a subgraph is a graph with any respect and fully complies with + * the Graph interface. + * + *

    If the base graph is a {@link org.jgrapht.ListenableGraph}, the subgraph + * listens on the base graph and guarantees the subgraph property. If an edge or + * a vertex is removed from the base graph, it is automatically removed from the + * subgraph. Subgraph listeners are informed on such removal only if it results + * in a cascaded removal from the subgraph. If the subgraph has been created as + * an induced subgraph it also keeps track of edges being added to its vertices. + * If vertices are added to the base graph, the subgraph remains unaffected.

    + * + *

    If the base graph is not a ListenableGraph, then the subgraph + * property cannot be guaranteed. If edges or vertices are removed from the base + * graph, they are not removed from the subgraph.

    + * + *

    Modifications to Subgraph are allowed as long as the subgraph property is + * maintained. Addition of vertices or edges are allowed as long as they also + * exist in the base graph. Removal of vertices or edges is always allowed. The + * base graph is never affected by any modification made to the + * subgraph.

    + * + *

    A subgraph may provide a "live-window" on a base graph, so that changes + * made to its vertices or edges are immediately reflected in the base graph, + * and vice versa. For that to happen, vertices and edges added to the subgraph + * must be identical (that is, reference-equal and not only value-equal) + * to their respective ones in the base graph. Previous versions of this class + * enforced such identity, at a severe performance cost. Currently it is no + * longer enforced. If you want to achieve a "live-window"functionality, your + * safest tactics would be to NOT override the equals() methods of + * your vertices and edges. If you use a class that has already overridden the + * equals() method, such as String, than you can use a + * wrapper around it, or else use it directly but exercise a great care to avoid + * having different-but-equal instances in the subgraph and the base graph.

    + * + *

    This graph implementation guarantees deterministic vertex and edge set + * ordering (via {@link LinkedHashSet}).

    + * + * @author Barak Naveh + * @see Graph + * @see Set + * @since Jul 18, 2003 + */ +public class Subgraph> + extends AbstractGraph + implements Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3208313055169665387L; + private static final String NO_SUCH_EDGE_IN_BASE = + "no such edge in base graph"; + private static final String NO_SUCH_VERTEX_IN_BASE = + "no such vertex in base graph"; + + //~ Instance fields -------------------------------------------------------- + + // + Set edgeSet = new LinkedHashSet(); // friendly to improve performance + Set vertexSet = new LinkedHashSet(); // friendly to improve + + // performance + + // + private transient Set unmodifiableEdgeSet = null; + private transient Set unmodifiableVertexSet = null; + private G base; + private boolean isInduced = false; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new Subgraph. + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + * @param edgeSubset edges to in include in the subgraph. If + * null then all the edges whose vertices found in the graph + * are included. + */ + public Subgraph(G base, Set vertexSubset, Set edgeSubset) + { + super(); + + this.base = base; + + if (edgeSubset == null) { + isInduced = true; + } + + if (base instanceof ListenableGraph) { + ((ListenableGraph) base).addGraphListener( + new BaseGraphListener()); + } + + addVerticesUsingFilter(base.vertexSet(), vertexSubset); + addEdgesUsingFilter(base.edgeSet(), edgeSubset); + } + + /** + * Creates a new induced Subgraph. The subgraph will keep track of edges + * being added to its vertex subset as well as deletion of edges and + * vertices. If base it not listenable, this is identical to the call + * Subgraph(base, vertexSubset, null) . + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + */ + public Subgraph(G base, Set vertexSubset) + { + this(base, vertexSubset, null); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#getAllEdges(Object, Object) + */ + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (containsVertex(sourceVertex) && containsVertex(targetVertex)) { + edges = new ArrayUnenforcedSet(); + + Set baseEdges = base.getAllEdges(sourceVertex, targetVertex); + + for (Iterator iter = baseEdges.iterator(); iter.hasNext();) { + E e = iter.next(); + + if (edgeSet.contains(e)) { // add if subgraph also contains + // it + edges.add(e); + } + } + } + + return edges; + } + + /** + * @see Graph#getEdge(Object, Object) + */ + public E getEdge(V sourceVertex, V targetVertex) + { + Set edges = getAllEdges(sourceVertex, targetVertex); + + if ((edges == null) || edges.isEmpty()) { + return null; + } else { + return edges.iterator().next(); + } + } + + /** + * @see Graph#getEdgeFactory() + */ + public EdgeFactory getEdgeFactory() + { + return base.getEdgeFactory(); + } + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + assertVertexExist(sourceVertex); + assertVertexExist(targetVertex); + + if (!base.containsEdge(sourceVertex, targetVertex)) { + throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE); + } + + Set edges = base.getAllEdges(sourceVertex, targetVertex); + + for (Iterator iter = edges.iterator(); iter.hasNext();) { + E e = iter.next(); + + if (!containsEdge(e)) { + edgeSet.add(e); + + return e; + } + } + + return null; + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + if (e == null) { + throw new NullPointerException(); + } + + if (!base.containsEdge(e)) { + throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE); + } + + assertVertexExist(sourceVertex); + assertVertexExist(targetVertex); + + assert (base.getEdgeSource(e) == sourceVertex); + assert (base.getEdgeTarget(e) == targetVertex); + + if (containsEdge(e)) { + return false; + } else { + edgeSet.add(e); + + return true; + } + } + + /** + * Adds the specified vertex to this subgraph. + * + * @param v the vertex to be added. + * + * @return true if the vertex was added, otherwise + * false. + * + * @throws NullPointerException + * @throws IllegalArgumentException + * + * @see Subgraph + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + if (v == null) { + throw new NullPointerException(); + } + + if (!base.containsVertex(v)) { + throw new IllegalArgumentException(NO_SUCH_VERTEX_IN_BASE); + } + + if (containsVertex(v)) { + return false; + } else { + vertexSet.add(v); + + return true; + } + } + + /** + * @see Graph#containsEdge(Object) + */ + public boolean containsEdge(E e) + { + return edgeSet.contains(e); + } + + /** + * @see Graph#containsVertex(Object) + */ + public boolean containsVertex(V v) + { + return vertexSet.contains(v); + } + + /** + * @see Graph#edgeSet() + */ + public Set edgeSet() + { + if (unmodifiableEdgeSet == null) { + unmodifiableEdgeSet = Collections.unmodifiableSet(edgeSet); + } + + return unmodifiableEdgeSet; + } + + /** + * @see Graph#edgesOf(Object) + */ + public Set edgesOf(V vertex) + { + assertVertexExist(vertex); + + Set edges = new ArrayUnenforcedSet(); + Set baseEdges = base.edgesOf(vertex); + + for (E e : baseEdges) { + if (containsEdge(e)) { + edges.add(e); + } + } + + return edges; + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + return edgeSet.remove(e); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + E e = getEdge(sourceVertex, targetVertex); + + return edgeSet.remove(e) ? e : null; + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + // If the base graph does NOT contain v it means we are here in + // response to removal of v from the base. In such case we don't need + // to remove all the edges of v as they were already removed. + if (containsVertex(v) && base.containsVertex(v)) { + removeAllEdges(edgesOf(v)); + } + + return vertexSet.remove(v); + } + + /** + * @see Graph#vertexSet() + */ + public Set vertexSet() + { + if (unmodifiableVertexSet == null) { + unmodifiableVertexSet = Collections.unmodifiableSet(vertexSet); + } + + return unmodifiableVertexSet; + } + + /** + * @see Graph#getEdgeSource(Object) + */ + public V getEdgeSource(E e) + { + return base.getEdgeSource(e); + } + + /** + * @see Graph#getEdgeTarget(Object) + */ + public V getEdgeTarget(E e) + { + return base.getEdgeTarget(e); + } + + private void addEdgesUsingFilter(Set edgeSet, Set filter) + { + E e; + boolean containsVertices; + boolean edgeIncluded; + + for (Iterator iter = edgeSet.iterator(); iter.hasNext();) { + e = iter.next(); + + V sourceVertex = base.getEdgeSource(e); + V targetVertex = base.getEdgeTarget(e); + containsVertices = + containsVertex(sourceVertex) + && containsVertex(targetVertex); + + // note the use of short circuit evaluation + edgeIncluded = (filter == null) || filter.contains(e); + + if (containsVertices && edgeIncluded) { + addEdge(sourceVertex, targetVertex, e); + } + } + } + + private void addVerticesUsingFilter(Set vertexSet, Set filter) + { + V v; + + for (Iterator iter = vertexSet.iterator(); iter.hasNext();) { + v = iter.next(); + + // note the use of short circuit evaluation + if ((filter == null) || filter.contains(v)) { + addVertex(v); + } + } + } + + public G getBase() + { + return base; + } + + /** + * @see Graph#getEdgeWeight(Object) + */ + public double getEdgeWeight(E e) + { + return base.getEdgeWeight(e); + } + + /** + * @see WeightedGraph#setEdgeWeight(Object, double) + */ + public void setEdgeWeight(E e, double weight) + { + ((WeightedGraph) base).setEdgeWeight(e, weight); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * An internal listener on the base graph. + * + * @author Barak Naveh + * @since Jul 20, 2003 + */ + private class BaseGraphListener + implements GraphListener, + Serializable + { + private static final long serialVersionUID = 4343535244243546391L; + + /** + * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) + */ + public void edgeAdded(GraphEdgeChangeEvent e) + { + if (isInduced) { + E edge = e.getEdge(); + V source = e.getEdgeSource(); + V target = e.getEdgeTarget(); + if (containsVertex(source) && containsVertex(target)) { + addEdge( + source, + target, + edge); + } + } + } + + /** + * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) + */ + public void edgeRemoved(GraphEdgeChangeEvent e) + { + E edge = e.getEdge(); + + removeEdge(edge); + } + + /** + * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) + */ + public void vertexAdded(GraphVertexChangeEvent e) + { + // we don't care + } + + /** + * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) + */ + public void vertexRemoved(GraphVertexChangeEvent e) + { + V vertex = e.getVertex(); + + removeVertex(vertex); + } + } +} + +// End Subgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedGraphUnion.java b/wdl/org/jgrapht/graph/UndirectedGraphUnion.java new file mode 100644 index 0000000..f6c4577 --- /dev/null +++ b/wdl/org/jgrapht/graph/UndirectedGraphUnion.java @@ -0,0 +1,81 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * UndirectedGraphUnion.java + * ------------------------- + * (C) Copyright 2009-2009, by Ilya Razenshteyn + * + * Original Author: Ilya Razenshteyn and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 02-Feb-2009 : Initial revision (IR); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +public class UndirectedGraphUnion + extends GraphUnion> + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -740199233080172450L; + + //~ Constructors ----------------------------------------------------------- + + UndirectedGraphUnion( + UndirectedGraph g1, + UndirectedGraphUnion g2, + WeightCombiner operator) + { + super(g1, g2, operator); + } + + UndirectedGraphUnion( + UndirectedGraph g1, + UndirectedGraphUnion g2) + { + super(g1, g2); + } + + //~ Methods ---------------------------------------------------------------- + + public int degreeOf(V vertex) + { + Set res = edgesOf(vertex); + return res.size(); + } +} + +// End UndirectedGraphUnion.java diff --git a/wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java b/wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java new file mode 100644 index 0000000..63c9fc6 --- /dev/null +++ b/wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java @@ -0,0 +1,64 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * UndirectedMaskSubgraph.java + * ------------------------- + * (C) Copyright 2007-2008, by France Telecom + * + * Original Author: Guillaume Boulmier and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 05-Jun-2007 : Initial revision (GB); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * An undirected graph that is a {@link MaskSubgraph} on another graph. + * + * @author Guillaume Boulmier + * @since July 5, 2007 + */ +public class UndirectedMaskSubgraph + extends MaskSubgraph + implements UndirectedGraph +{ + //~ Constructors ----------------------------------------------------------- + + public UndirectedMaskSubgraph( + UndirectedGraph base, + MaskFunctor mask) + { + super(base, mask); + } +} + +// End UndirectedMaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedSubgraph.java b/wdl/org/jgrapht/graph/UndirectedSubgraph.java new file mode 100644 index 0000000..381fa99 --- /dev/null +++ b/wdl/org/jgrapht/graph/UndirectedSubgraph.java @@ -0,0 +1,106 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------- + * UndirectedSubgraph.java + * ----------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * An undirected graph that is a subgraph on other graph. + * + * @see Subgraph + */ +public class UndirectedSubgraph + extends Subgraph> + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3256728359772631350L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new undirected subgraph. + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + * @param edgeSubset edges to in include in the subgraph. If + * null then all the edges whose vertices found in the graph + * are included. + */ + public UndirectedSubgraph( + UndirectedGraph base, + Set vertexSubset, + Set edgeSubset) + { + super(base, vertexSubset, edgeSubset); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see UndirectedGraph#degreeOf(Object) + */ + public int degreeOf(V vertex) + { + assertVertexExist(vertex); + + int degree = 0; + + for (E e : getBase().edgesOf(vertex)) { + if (containsEdge(e)) { + degree++; + + if (getEdgeSource(e).equals(getEdgeTarget(e))) { + degree++; + } + } + } + + return degree; + } +} + +// End UndirectedSubgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java b/wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java new file mode 100644 index 0000000..b7bde41 --- /dev/null +++ b/wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java @@ -0,0 +1,82 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------- + * UndirectedWeightedSubgraph.java + * ------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * + */ +package org.jgrapht.graph; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * An undirected weighted graph that is a subgraph on other graph. + * + * @see Subgraph + */ +public class UndirectedWeightedSubgraph + extends UndirectedSubgraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3689346615735236409L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new undirected weighted subgraph. + * + * @param base the base (backing) graph on which the subgraph will be based. + * @param vertexSubset vertices to include in the subgraph. If + * null then all vertices are included. + * @param edgeSubset edges to in include in the subgraph. If + * null then all the edges whose vertices found in the graph + * are included. + */ + public UndirectedWeightedSubgraph( + WeightedGraph base, + Set vertexSubset, + Set edgeSubset) + { + super((UndirectedGraph) base, vertexSubset, edgeSubset); + } +} + +// End UndirectedWeightedSubgraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java b/wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java new file mode 100644 index 0000000..67ec241 --- /dev/null +++ b/wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java @@ -0,0 +1,74 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------------ + * UnmodifiableDirectedGraph.java + * ------------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A directed graph that cannot be modified. + * + * @see UnmodifiableGraph + */ +public class UnmodifiableDirectedGraph + extends UnmodifiableGraph + implements DirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3978701783725913906L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new unmodifiable directed graph based on the specified backing + * graph. + * + * @param g the backing graph on which an unmodifiable graph is to be + * created. + */ + public UnmodifiableDirectedGraph(DirectedGraph g) + { + super(g); + } +} + +// End UnmodifiableDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableGraph.java b/wdl/org/jgrapht/graph/UnmodifiableGraph.java new file mode 100644 index 0000000..6455120 --- /dev/null +++ b/wdl/org/jgrapht/graph/UnmodifiableGraph.java @@ -0,0 +1,164 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * UnmodifiableGraph.java + * ---------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH); + * 07-May-2006 : Changed from List to Set (JVS); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import java.io.*; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * An unmodifiable view of the backing graph specified in the constructor. This + * graph allows modules to provide users with "read-only" access to internal + * graphs. Query operations on this graph "read through" to the backing graph, + * and attempts to modify this graph result in an + * UnsupportedOperationException. + * + *

    This graph does not pass the hashCode and equals operations through + * to the backing graph, but relies on Object's equals and + * hashCode methods. This graph will be serializable if the backing + * graph is serializable.

    + * + * @author Barak Naveh + * @since Jul 24, 2003 + */ +public class UnmodifiableGraph + extends GraphDelegator + implements Serializable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3544957670722713913L; + private static final String UNMODIFIABLE = "this graph is unmodifiable"; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new unmodifiable graph based on the specified backing graph. + * + * @param g the backing graph on which an unmodifiable graph is to be + * created. + */ + public UnmodifiableGraph(Graph g) + { + super(g); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see Graph#addEdge(Object, Object) + */ + public E addEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#addVertex(Object) + */ + public boolean addVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllEdges(Collection) + */ + public boolean removeAllEdges(Collection edges) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllEdges(Object, Object) + */ + public Set removeAllEdges(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeAllVertices(Collection) + */ + public boolean removeAllVertices(Collection vertices) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(Object) + */ + public boolean removeEdge(E e) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeEdge(Object, Object) + */ + public E removeEdge(V sourceVertex, V targetVertex) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } + + /** + * @see Graph#removeVertex(Object) + */ + public boolean removeVertex(V v) + { + throw new UnsupportedOperationException(UNMODIFIABLE); + } +} + +// End UnmodifiableGraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java b/wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java new file mode 100644 index 0000000..2024ac9 --- /dev/null +++ b/wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java @@ -0,0 +1,74 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------------- + * UnmodifiableUndirectedGraph.java + * -------------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 11-Mar-2004 : Made generic (CH) + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * An undirected graph that cannot be modified. + * + * @see UnmodifiableGraph + */ +public class UnmodifiableUndirectedGraph + extends UnmodifiableGraph + implements UndirectedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3258134639355704624L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new unmodifiable undirected graph based on the specified + * backing graph. + * + * @param g the backing graph on which an unmodifiable graph is to be + * created. + */ + public UnmodifiableUndirectedGraph(UndirectedGraph g) + { + super(g); + } +} + +// End UnmodifiableUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/WeightedMultigraph.java b/wdl/org/jgrapht/graph/WeightedMultigraph.java new file mode 100644 index 0000000..339f55e --- /dev/null +++ b/wdl/org/jgrapht/graph/WeightedMultigraph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------- + * WeightedMultigraph.java + * ----------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A weighted multigraph. A weighted multigraph is a non-simple undirected graph + * in which no loops are permitted, but multiple edges between any two vertices + * are. The edges of a weighted multigraph have weights. If you're unsure about + * multigraphs, see: + * http://mathworld.wolfram.com/Multigraph.html. + */ +public class WeightedMultigraph + extends Multigraph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3544671793370640696L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new weighted multigraph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public WeightedMultigraph(EdgeFactory ef) + { + super(ef); + } + + /** + * Creates a new weighted multigraph. + * + * @param edgeClass class on which to base factory for edges + */ + public WeightedMultigraph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } +} + +// End WeightedMultigraph.java diff --git a/wdl/org/jgrapht/graph/WeightedPseudograph.java b/wdl/org/jgrapht/graph/WeightedPseudograph.java new file mode 100644 index 0000000..f8b1030 --- /dev/null +++ b/wdl/org/jgrapht/graph/WeightedPseudograph.java @@ -0,0 +1,85 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------ + * WeightedPseudograph.java + * ------------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 05-Aug-2003 : Initial revision (BN); + * 06-Aug-2005 : Made generic (CH); + * 28-May-2006 : Moved connectivity info from edge to graph (JVS); + * + */ +package org.jgrapht.graph; + +import org.jgrapht.*; + + +/** + * A weighted pseudograph. A weighted pseudograph is a non-simple undirected + * graph in which both graph loops and multiple edges are permitted. The edges + * of a weighted pseudograph have weights. If you're unsure about pseudographs, + * see: + * http://mathworld.wolfram.com/Pseudograph.html. + */ +public class WeightedPseudograph + extends Pseudograph + implements WeightedGraph +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3257290244524356152L; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new weighted pseudograph with the specified edge factory. + * + * @param ef the edge factory of the new graph. + */ + public WeightedPseudograph(EdgeFactory ef) + { + super(ef); + } + + /** + * Creates a new weighted pseudograph. + * + * @param edgeClass class on which to base factory for edges + */ + public WeightedPseudograph(Class edgeClass) + { + this(new ClassBasedEdgeFactory(edgeClass)); + } +} + +// End WeightedPseudograph.java diff --git a/wdl/org/jgrapht/graph/package.html b/wdl/org/jgrapht/graph/package.html new file mode 100644 index 0000000..10fca41 --- /dev/null +++ b/wdl/org/jgrapht/graph/package.html @@ -0,0 +1,6 @@ + + + +Implementations of various graphs. + + \ No newline at end of file diff --git a/wdl/org/jgrapht/package.html b/wdl/org/jgrapht/package.html new file mode 100644 index 0000000..76a5567 --- /dev/null +++ b/wdl/org/jgrapht/package.html @@ -0,0 +1,7 @@ + + + +The front-end API's interfaces and classes, including {@link org.jgrapht.Graph}, +{@link org.jgrapht.DirectedGraph} and {@link org.jgrapht.UndirectedGraph}. + + diff --git a/wdl/org/jgrapht/traverse/AbstractGraphIterator.java b/wdl/org/jgrapht/traverse/AbstractGraphIterator.java new file mode 100644 index 0000000..5ab37b5 --- /dev/null +++ b/wdl/org/jgrapht/traverse/AbstractGraphIterator.java @@ -0,0 +1,217 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * AbstractGraphIterator.java + * -------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 11-Aug-2003 : Adaptation to new event model (BN); + * 04-May-2004 : Made generic (CH) + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.event.*; + + +/** + * An empty implementation of a graph iterator to minimize the effort required + * to implement graph iterators. + * + * @author Barak Naveh + * @since Jul 19, 2003 + */ +public abstract class AbstractGraphIterator + implements GraphIterator +{ + //~ Instance fields -------------------------------------------------------- + + private List> traversalListeners = + new ArrayList>(); + private boolean crossComponentTraversal = true; + private boolean reuseEvents = false; + + // We keep this cached redundantly with traversalListeners.size() + // so that subclasses can use it as a fast check to see if + // event firing calls can be skipped. + protected int nListeners = 0; + + //~ Methods ---------------------------------------------------------------- + + /** + * Sets the cross component traversal flag - indicates whether to traverse + * the graph across connected components. + * + * @param crossComponentTraversal if true traverses across + * connected components. + */ + public void setCrossComponentTraversal(boolean crossComponentTraversal) + { + this.crossComponentTraversal = crossComponentTraversal; + } + + /** + * Test whether this iterator is set to traverse the graph across connected + * components. + * + * @return true if traverses across connected components, + * otherwise false. + */ + public boolean isCrossComponentTraversal() + { + return crossComponentTraversal; + } + + /** + * @see GraphIterator#setReuseEvents(boolean) + */ + public void setReuseEvents(boolean reuseEvents) + { + this.reuseEvents = reuseEvents; + } + + /** + * @see GraphIterator#isReuseEvents() + */ + public boolean isReuseEvents() + { + return reuseEvents; + } + + /** + * Adds the specified traversal listener to this iterator. + * + * @param l the traversal listener to be added. + */ + public void addTraversalListener(TraversalListener l) + { + if (!traversalListeners.contains(l)) { + traversalListeners.add(l); + nListeners = traversalListeners.size(); + } + } + + /** + * Unsupported. + * + * @throws UnsupportedOperationException + */ + public void remove() + { + throw new UnsupportedOperationException(); + } + + /** + * Removes the specified traversal listener from this iterator. + * + * @param l the traversal listener to be removed. + */ + public void removeTraversalListener(TraversalListener l) + { + traversalListeners.remove(l); + nListeners = traversalListeners.size(); + } + + /** + * Informs all listeners that the traversal of the current connected + * component finished. + * + * @param e the connected component finished event. + */ + protected void fireConnectedComponentFinished( + ConnectedComponentTraversalEvent e) + { + for (int i = 0; i < nListeners; i++) { + TraversalListener l = traversalListeners.get(i); + l.connectedComponentFinished(e); + } + } + + /** + * Informs all listeners that a traversal of a new connected component has + * started. + * + * @param e the connected component started event. + */ + protected void fireConnectedComponentStarted( + ConnectedComponentTraversalEvent e) + { + for (int i = 0; i < nListeners; i++) { + TraversalListener l = traversalListeners.get(i); + l.connectedComponentStarted(e); + } + } + + /** + * Informs all listeners that a the specified edge was visited. + * + * @param e the edge traversal event. + */ + protected void fireEdgeTraversed(EdgeTraversalEvent e) + { + for (int i = 0; i < nListeners; i++) { + TraversalListener l = traversalListeners.get(i); + l.edgeTraversed(e); + } + } + + /** + * Informs all listeners that a the specified vertex was visited. + * + * @param e the vertex traversal event. + */ + protected void fireVertexTraversed(VertexTraversalEvent e) + { + for (int i = 0; i < nListeners; i++) { + TraversalListener l = traversalListeners.get(i); + l.vertexTraversed(e); + } + } + + /** + * Informs all listeners that a the specified vertex was finished. + * + * @param e the vertex traversal event. + */ + protected void fireVertexFinished(VertexTraversalEvent e) + { + for (int i = 0; i < nListeners; i++) { + TraversalListener l = traversalListeners.get(i); + l.vertexFinished(e); + } + } +} + +// End AbstractGraphIterator.java diff --git a/wdl/org/jgrapht/traverse/BreadthFirstIterator.java b/wdl/org/jgrapht/traverse/BreadthFirstIterator.java new file mode 100644 index 0000000..a053588 --- /dev/null +++ b/wdl/org/jgrapht/traverse/BreadthFirstIterator.java @@ -0,0 +1,130 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * BreadthFirstIterator.java + * ------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Liviu Rau + * Christian Hammer + * Ross Judson + * + * $Id$ + * + * Changes + * ------- + * 24-Jul-2003 : Initial revision (BN); + * 06-Aug-2003 : Extracted common logic to TraverseUtils.XXFirstIterator (BN); + * 31-Jan-2004 : Reparented and changed interface to parent class (BN); + * 28-Sep-2008 : Optimized using ArrayDeque per suggestion from Ross (JVS) + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.*; + + +/** + * A breadth-first iterator for a directed and an undirected graph. For this + * iterator to work correctly the graph must not be modified during iteration. + * Currently there are no means to ensure that, nor to fail-fast. The results of + * such modifications are undefined. + * + * @author Barak Naveh + * @since Jul 19, 2003 + */ +public class BreadthFirstIterator + extends CrossComponentIterator +{ + //~ Instance fields -------------------------------------------------------- + + private Deque queue = new ArrayDeque(); + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new breadth-first iterator for the specified graph. + * + * @param g the graph to be iterated. + */ + public BreadthFirstIterator(Graph g) + { + this(g, null); + } + + /** + * Creates a new breadth-first iterator for the specified graph. Iteration + * will start at the specified start vertex and will be limited to the + * connected component that includes that vertex. If the specified start + * vertex is null, iteration will start at an arbitrary vertex + * and will not be limited, that is, will be able to traverse all the graph. + * + * @param g the graph to be iterated. + * @param startVertex the vertex iteration to be started. + */ + public BreadthFirstIterator(Graph g, V startVertex) + { + super(g, startVertex); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see CrossComponentIterator#isConnectedComponentExhausted() + */ + protected boolean isConnectedComponentExhausted() + { + return queue.isEmpty(); + } + + /** + * @see CrossComponentIterator#encounterVertex(Object, Object) + */ + protected void encounterVertex(V vertex, E edge) + { + putSeenData(vertex, null); + queue.add(vertex); + } + + /** + * @see CrossComponentIterator#encounterVertexAgain(Object, Object) + */ + protected void encounterVertexAgain(V vertex, E edge) + { + } + + /** + * @see CrossComponentIterator#provideNextVertex() + */ + protected V provideNextVertex() + { + return queue.removeFirst(); + } +} + +// End BreadthFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/ClosestFirstIterator.java b/wdl/org/jgrapht/traverse/ClosestFirstIterator.java new file mode 100644 index 0000000..970fb38 --- /dev/null +++ b/wdl/org/jgrapht/traverse/ClosestFirstIterator.java @@ -0,0 +1,338 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * ClosestFirstIterator.java + * ------------------------- + * (C) Copyright 2003-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): Barak Naveh + * + * $Id$ + * + * Changes + * ------- + * 02-Sep-2003 : Initial revision (JVS); + * 31-Jan-2004 : Reparented and changed interface to parent class (BN); + * 29-May-2005 : Added radius support (JVS); + * 06-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.traverse; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * A closest-first iterator for a directed or undirected graph. For this + * iterator to work correctly the graph must not be modified during iteration. + * Currently there are no means to ensure that, nor to fail-fast. The results of + * such modifications are undefined. + * + *

    The metric for closest here is the path length from a start vertex. + * Graph.getEdgeWeight(Edge) is summed to calculate path length. Negative edge + * weights will result in an IllegalArgumentException. Optionally, path length + * may be bounded by a finite radius.

    + * + * @author John V. Sichi + * @since Sep 2, 2003 + */ +public class ClosestFirstIterator + extends CrossComponentIterator>> +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Priority queue of fringe vertices. + */ + private FibonacciHeap> heap = + new FibonacciHeap>(); + + /** + * Maximum distance to search. + */ + private double radius = Double.POSITIVE_INFINITY; + + private boolean initialized = false; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new closest-first iterator for the specified graph. + * + * @param g the graph to be iterated. + */ + public ClosestFirstIterator(Graph g) + { + this(g, null); + } + + /** + * Creates a new closest-first iterator for the specified graph. Iteration + * will start at the specified start vertex and will be limited to the + * connected component that includes that vertex. If the specified start + * vertex is null, iteration will start at an arbitrary vertex + * and will not be limited, that is, will be able to traverse all the graph. + * + * @param g the graph to be iterated. + * @param startVertex the vertex iteration to be started. + */ + public ClosestFirstIterator(Graph g, V startVertex) + { + this(g, startVertex, Double.POSITIVE_INFINITY); + } + + /** + * Creates a new radius-bounded closest-first iterator for the specified + * graph. Iteration will start at the specified start vertex and will be + * limited to the subset of the connected component which includes that + * vertex and is reachable via paths of length less than or equal to the + * specified radius. The specified start vertex may not be + * null. + * + * @param g the graph to be iterated. + * @param startVertex the vertex iteration to be started. + * @param radius limit on path length, or Double.POSITIVE_INFINITY for + * unbounded search. + */ + public ClosestFirstIterator(Graph g, V startVertex, double radius) + { + super(g, startVertex); + this.radius = radius; + checkRadiusTraversal(isCrossComponentTraversal()); + initialized = true; + } + + //~ Methods ---------------------------------------------------------------- + + // override AbstractGraphIterator + public void setCrossComponentTraversal(boolean crossComponentTraversal) + { + if (initialized) { + checkRadiusTraversal(crossComponentTraversal); + } + super.setCrossComponentTraversal(crossComponentTraversal); + } + + /** + * Get the length of the shortest path known to the given vertex. If the + * vertex has already been visited, then it is truly the shortest path + * length; otherwise, it is the best known upper bound. + * + * @param vertex vertex being sought from start vertex + * + * @return length of shortest path known, or Double.POSITIVE_INFINITY if no + * path found yet + */ + public double getShortestPathLength(V vertex) + { + FibonacciHeapNode> node = getSeenData(vertex); + + if (node == null) { + return Double.POSITIVE_INFINITY; + } + + return node.getKey(); + } + + /** + * Get the spanning tree edge reaching a vertex which has been seen already + * in this traversal. This edge is the last link in the shortest known path + * between the start vertex and the requested vertex. If the vertex has + * already been visited, then it is truly the minimum spanning tree edge; + * otherwise, it is the best candidate seen so far. + * + * @param vertex the spanned vertex. + * + * @return the spanning tree edge, or null if the vertex either has not been + * seen yet or is the start vertex. + */ + public E getSpanningTreeEdge(V vertex) + { + FibonacciHeapNode> node = getSeenData(vertex); + + if (node == null) { + return null; + } + + return node.getData().spanningTreeEdge; + } + + /** + * @see CrossComponentIterator#isConnectedComponentExhausted() + */ + protected boolean isConnectedComponentExhausted() + { + if (heap.size() == 0) { + return true; + } else { + if (heap.min().getKey() > radius) { + heap.clear(); + + return true; + } else { + return false; + } + } + } + + /** + * @see CrossComponentIterator#encounterVertex(Object, Object) + */ + protected void encounterVertex(V vertex, E edge) + { + double shortestPathLength; + if (edge == null) { + shortestPathLength = 0; + } else { + shortestPathLength = calculatePathLength(vertex, edge); + } + FibonacciHeapNode> node = createSeenData(vertex, edge); + putSeenData(vertex, node); + heap.insert(node, shortestPathLength); + } + + /** + * Override superclass. When we see a vertex again, we need to see if the + * new edge provides a shorter path than the old edge. + * + * @param vertex the vertex re-encountered + * @param edge the edge via which the vertex was re-encountered + */ + protected void encounterVertexAgain(V vertex, E edge) + { + FibonacciHeapNode> node = getSeenData(vertex); + + if (node.getData().frozen) { + // no improvement for this vertex possible + return; + } + + double candidatePathLength = calculatePathLength(vertex, edge); + + if (candidatePathLength < node.getKey()) { + node.getData().spanningTreeEdge = edge; + heap.decreaseKey(node, candidatePathLength); + } + } + + /** + * @see CrossComponentIterator#provideNextVertex() + */ + protected V provideNextVertex() + { + FibonacciHeapNode> node = heap.removeMin(); + node.getData().frozen = true; + + return node.getData().vertex; + } + + private void assertNonNegativeEdge(E edge) + { + if (getGraph().getEdgeWeight(edge) < 0) { + throw new IllegalArgumentException( + "negative edge weights not allowed"); + } + } + + /** + * Determine path length to a vertex via an edge, using the path length for + * the opposite vertex. + * + * @param vertex the vertex for which to calculate the path length. + * @param edge the edge via which the path is being extended. + * + * @return calculated path length. + */ + private double calculatePathLength(V vertex, E edge) + { + assertNonNegativeEdge(edge); + + V otherVertex = Graphs.getOppositeVertex(getGraph(), edge, vertex); + FibonacciHeapNode> otherEntry = + getSeenData(otherVertex); + + return otherEntry.getKey() + + getGraph().getEdgeWeight(edge); + } + + private void checkRadiusTraversal(boolean crossComponentTraversal) + { + if (crossComponentTraversal && (radius != Double.POSITIVE_INFINITY)) { + throw new IllegalArgumentException( + "radius may not be specified for cross-component traversal"); + } + } + + /** + * The first time we see a vertex, make up a new heap node for it. + * + * @param vertex a vertex which has just been encountered. + * @param edge the edge via which the vertex was encountered. + * + * @return the new heap node. + */ + private FibonacciHeapNode> createSeenData( + V vertex, + E edge) + { + QueueEntry entry = new QueueEntry(); + entry.vertex = vertex; + entry.spanningTreeEdge = edge; + + return new FibonacciHeapNode>(entry); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Private data to associate with each entry in the priority queue. + */ + static class QueueEntry + { + /** + * Best spanning tree edge to vertex seen so far. + */ + E spanningTreeEdge; + + /** + * The vertex reached. + */ + V vertex; + + /** + * True once spanningTreeEdge is guaranteed to be the true minimum. + */ + boolean frozen; + + QueueEntry() + { + } + } +} + +// End ClosestFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/CrossComponentIterator.java b/wdl/org/jgrapht/traverse/CrossComponentIterator.java new file mode 100644 index 0000000..dbf1599 --- /dev/null +++ b/wdl/org/jgrapht/traverse/CrossComponentIterator.java @@ -0,0 +1,570 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* --------------------------- + * CrossComponentIterator.java + * --------------------------- + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): John V. Sichi + * Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 31-Jul-2003 : Initial revision (BN); + * 11-Aug-2003 : Adaptation to new event model (BN); + * 31-Jan-2004 : Extracted cross-component traversal functionality (BN); + * 04-May-2004 : Made generic (CH) + * 07-May-2006 : Changed from List to Set (JVS); + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.event.*; + + +/** + * Provides a cross-connected-component traversal functionality for iterator + * subclasses. + * + * @param vertex type + * @param edge type + * @param type of data associated to seen vertices + * + * @author Barak Naveh + * @since Jan 31, 2004 + */ +public abstract class CrossComponentIterator + extends AbstractGraphIterator +{ + //~ Static fields/initializers --------------------------------------------- + + private static final int CCS_BEFORE_COMPONENT = 1; + private static final int CCS_WITHIN_COMPONENT = 2; + private static final int CCS_AFTER_COMPONENT = 3; + + //~ Enums ------------------------------------------------------------------ + + /** + * Standard vertex visit state enumeration. + */ + protected static enum VisitColor + { + /** + * Vertex has not been returned via iterator yet. + */ + WHITE, + + /** + * Vertex has been returned via iterator, but we're not done with all of + * its out-edges yet. + */ + GRAY, + + /** + * Vertex has been returned via iterator, and we're done with all of its + * out-edges. + */ + BLACK + } + + //~ Instance fields -------------------------------------------------------- + + // + private final ConnectedComponentTraversalEvent ccFinishedEvent = + new ConnectedComponentTraversalEvent( + this, + ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_FINISHED); + private final ConnectedComponentTraversalEvent ccStartedEvent = + new ConnectedComponentTraversalEvent( + this, + ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_STARTED); + + // TODO: support ConcurrentModificationException if graph modified + // during iteration. + private FlyweightEdgeEvent reusableEdgeEvent; + private FlyweightVertexEvent reusableVertexEvent; + private Iterator vertexIterator = null; + + /** + * Stores the vertices that have been seen during iteration and (optionally) + * some additional traversal info regarding each vertex. + */ + private Map seen = new HashMap(); + private V startVertex; + private Specifics specifics; + + private final Graph graph; + + /** + * The connected component state + */ + private int state = CCS_BEFORE_COMPONENT; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new iterator for the specified graph. Iteration will start at + * the specified start vertex. If the specified start vertex is + * null, Iteration will start at an arbitrary graph vertex. + * + * @param g the graph to be iterated. + * @param startVertex the vertex iteration to be started. + * + * @throws IllegalArgumentException if g==null or does not + * contain startVertex + */ + public CrossComponentIterator(Graph g, V startVertex) + { + super(); + + if (g == null) { + throw new IllegalArgumentException("graph must not be null"); + } + graph = g; + + specifics = createGraphSpecifics(g); + vertexIterator = g.vertexSet().iterator(); + setCrossComponentTraversal(startVertex == null); + + reusableEdgeEvent = new FlyweightEdgeEvent(this, null); + reusableVertexEvent = new FlyweightVertexEvent(this, null); + + if (startVertex == null) { + // pick a start vertex if graph not empty + if (vertexIterator.hasNext()) { + this.startVertex = vertexIterator.next(); + } else { + this.startVertex = null; + } + } else if (g.containsVertex(startVertex)) { + this.startVertex = startVertex; + } else { + throw new IllegalArgumentException( + "graph must contain the start vertex"); + } + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @return the graph being traversed + */ + public Graph getGraph() + { + return graph; + } + + /** + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() + { + if (startVertex != null) { + encounterStartVertex(); + } + + if (isConnectedComponentExhausted()) { + if (state == CCS_WITHIN_COMPONENT) { + state = CCS_AFTER_COMPONENT; + if (nListeners != 0) { + fireConnectedComponentFinished(ccFinishedEvent); + } + } + + if (isCrossComponentTraversal()) { + while (vertexIterator.hasNext()) { + V v = vertexIterator.next(); + + if (!isSeenVertex(v)) { + encounterVertex(v, null); + state = CCS_BEFORE_COMPONENT; + + return true; + } + } + + return false; + } else { + return false; + } + } else { + return true; + } + } + + /** + * @see java.util.Iterator#next() + */ + public V next() + { + if (startVertex != null) { + encounterStartVertex(); + } + + if (hasNext()) { + if (state == CCS_BEFORE_COMPONENT) { + state = CCS_WITHIN_COMPONENT; + if (nListeners != 0) { + fireConnectedComponentStarted(ccStartedEvent); + } + } + + V nextVertex = provideNextVertex(); + if (nListeners != 0) { + fireVertexTraversed(createVertexTraversalEvent(nextVertex)); + } + + addUnseenChildrenOf(nextVertex); + + return nextVertex; + } else { + throw new NoSuchElementException(); + } + } + + /** + * Returns true if there are no more uniterated vertices in the + * currently iterated connected component; false otherwise. + * + * @return true if there are no more uniterated vertices in the + * currently iterated connected component; false otherwise. + */ + protected abstract boolean isConnectedComponentExhausted(); + + /** + * Update data structures the first time we see a vertex. + * + * @param vertex the vertex encountered + * @param edge the edge via which the vertex was encountered, or null if the + * vertex is a starting point + */ + protected abstract void encounterVertex(V vertex, E edge); + + /** + * Returns the vertex to be returned in the following call to the iterator + * next method. + * + * @return the next vertex to be returned by this iterator. + */ + protected abstract V provideNextVertex(); + + /** + * Access the data stored for a seen vertex. + * + * @param vertex a vertex which has already been seen. + * + * @return data associated with the seen vertex or null if no + * data was associated with the vertex. A null return can also + * indicate that the vertex was explicitly associated with + * null. + */ + protected D getSeenData(V vertex) + { + return seen.get(vertex); + } + + /** + * Determines whether a vertex has been seen yet by this traversal. + * + * @param vertex vertex in question + * + * @return true if vertex has already been seen + */ + protected boolean isSeenVertex(Object vertex) + { + return seen.containsKey(vertex); + } + + /** + * Called whenever we re-encounter a vertex. The default implementation does + * nothing. + * + * @param vertex the vertex re-encountered + * @param edge the edge via which the vertex was re-encountered + */ + protected abstract void encounterVertexAgain(V vertex, E edge); + + /** + * Stores iterator-dependent data for a vertex that has been seen. + * + * @param vertex a vertex which has been seen. + * @param data data to be associated with the seen vertex. + * + * @return previous value associated with specified vertex or + * null if no data was associated with the vertex. A + * null return can also indicate that the vertex was explicitly + * associated with null. + */ + protected D putSeenData(V vertex, D data) + { + return seen.put(vertex, data); + } + + /** + * Called when a vertex has been finished (meaning is dependent on traversal + * represented by subclass). + * + * @param vertex vertex which has been finished + */ + protected void finishVertex(V vertex) + { + if (nListeners != 0) { + fireVertexFinished(createVertexTraversalEvent(vertex)); + } + } + + // ------------------------------------------------------------------------- + /** + * @param + * @param + * @param g + * + * @return TODO Document me + */ + static Specifics createGraphSpecifics(Graph g) + { + if (g instanceof DirectedGraph) { + return new DirectedSpecifics((DirectedGraph) g); + } else { + return new UndirectedSpecifics(g); + } + } + + private void addUnseenChildrenOf(V vertex) + { + for (E edge : specifics.edgesOf(vertex)) { + if (nListeners != 0) { + fireEdgeTraversed(createEdgeTraversalEvent(edge)); + } + + V oppositeV = Graphs.getOppositeVertex(graph, edge, vertex); + + if (isSeenVertex(oppositeV)) { + encounterVertexAgain(oppositeV, edge); + } else { + encounterVertex(oppositeV, edge); + } + } + } + + private EdgeTraversalEvent createEdgeTraversalEvent(E edge) + { + if (isReuseEvents()) { + reusableEdgeEvent.setEdge(edge); + + return reusableEdgeEvent; + } else { + return new EdgeTraversalEvent(this, edge); + } + } + + private VertexTraversalEvent createVertexTraversalEvent(V vertex) + { + if (isReuseEvents()) { + reusableVertexEvent.setVertex(vertex); + + return reusableVertexEvent; + } else { + return new VertexTraversalEvent(this, vertex); + } + } + + private void encounterStartVertex() + { + encounterVertex(startVertex, null); + startVertex = null; + } + + //~ Inner Interfaces ------------------------------------------------------- + + static interface SimpleContainer + { + /** + * Tests if this container is empty. + * + * @return true if empty, otherwise false. + */ + public boolean isEmpty(); + + /** + * Adds the specified object to this container. + * + * @param o the object to be added. + */ + public void add(T o); + + /** + * Remove an object from this container and return it. + * + * @return the object removed from this container. + */ + public T remove(); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Provides unified interface for operations that are different in directed + * graphs and in undirected graphs. + */ + abstract static class Specifics + { + /** + * Returns the edges outgoing from the specified vertex in case of + * directed graph, and the edge touching the specified vertex in case of + * undirected graph. + * + * @param vertex the vertex whose outgoing edges are to be returned. + * + * @return the edges outgoing from the specified vertex in case of + * directed graph, and the edge touching the specified vertex in case of + * undirected graph. + */ + public abstract Set edgesOf(VV vertex); + } + + /** + * A reusable edge event. + * + * @author Barak Naveh + * @since Aug 11, 2003 + */ + static class FlyweightEdgeEvent + extends EdgeTraversalEvent + { + private static final long serialVersionUID = 4051327833765000755L; + + /** + * @see EdgeTraversalEvent#EdgeTraversalEvent(Object, Edge) + */ + public FlyweightEdgeEvent(Object eventSource, localE edge) + { + super(eventSource, edge); + } + + /** + * Sets the edge of this event. + * + * @param edge the edge to be set. + */ + protected void setEdge(localE edge) + { + this.edge = edge; + } + } + + /** + * A reusable vertex event. + * + * @author Barak Naveh + * @since Aug 11, 2003 + */ + static class FlyweightVertexEvent + extends VertexTraversalEvent + { + private static final long serialVersionUID = 3834024753848399924L; + + /** + * @see VertexTraversalEvent#VertexTraversalEvent(Object, Object) + */ + public FlyweightVertexEvent(Object eventSource, VV vertex) + { + super(eventSource, vertex); + } + + /** + * Sets the vertex of this event. + * + * @param vertex the vertex to be set. + */ + protected void setVertex(VV vertex) + { + this.vertex = vertex; + } + } + + /** + * An implementation of {@link Specifics} for a directed graph. + */ + private static class DirectedSpecifics + extends Specifics + { + private DirectedGraph graph; + + /** + * Creates a new DirectedSpecifics object. + * + * @param g the graph for which this specifics object to be created. + */ + public DirectedSpecifics(DirectedGraph g) + { + graph = g; + } + + /** + * @see CrossComponentIterator.Specifics#edgesOf(Object) + */ + public Set edgesOf(VV vertex) + { + return graph.outgoingEdgesOf(vertex); + } + } + + /** + * An implementation of {@link Specifics} in which edge direction (if any) + * is ignored. + */ + private static class UndirectedSpecifics + extends Specifics + { + private Graph graph; + + /** + * Creates a new UndirectedSpecifics object. + * + * @param g the graph for which this specifics object to be created. + */ + public UndirectedSpecifics(Graph g) + { + graph = g; + } + + /** + * @see CrossComponentIterator.Specifics#edgesOf(Object) + */ + public Set edgesOf(VV vertex) + { + return graph.edgesOf(vertex); + } + } +} + +// End CrossComponentIterator.java diff --git a/wdl/org/jgrapht/traverse/DepthFirstIterator.java b/wdl/org/jgrapht/traverse/DepthFirstIterator.java new file mode 100644 index 0000000..fec48e9 --- /dev/null +++ b/wdl/org/jgrapht/traverse/DepthFirstIterator.java @@ -0,0 +1,223 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------- + * DepthFirstIterator.java + * ----------------------- + * (C) Copyright 2003-2008, by Liviu Rau and Contributors. + * + * Original Author: Liviu Rau + * Contributor(s): Barak Naveh + * Christian Hammer + * Welson Sun + * Ross Judson + * + * $Id$ + * + * Changes + * ------- + * 29-Jul-2003 : Initial revision (LR); + * 31-Jul-2003 : Fixed traversal across connected components (BN); + * 06-Aug-2003 : Extracted common logic to TraverseUtils.XXFirstIterator (BN); + * 31-Jan-2004 : Reparented and changed interface to parent class (BN); + * 04-May-2004 : Made generic (CH) + * 27-Aug-2006 : Added WHITE/GRAY/BLACK to fix bug reported by Welson Sun (JVS) + * 28-Sep-2008 : Optimized using ArrayDeque per suggestion from Ross (JVS) + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * A depth-first iterator for a directed and an undirected graph. For this + * iterator to work correctly the graph must not be modified during iteration. + * Currently there are no means to ensure that, nor to fail-fast. The results of + * such modifications are undefined. + * + * @author Liviu Rau + * @author Barak Naveh + * @since Jul 29, 2003 + */ +public class DepthFirstIterator + extends CrossComponentIterator +{ + //~ Static fields/initializers --------------------------------------------- + + /** + * Sentinel object. Unfortunately, we can't use null, because ArrayDeque + * won't accept those. And we don't want to rely on the caller to provide a + * sentinel object for us. So we have to play typecasting games. + */ + public static final Object SENTINEL = new Object(); + + //~ Instance fields -------------------------------------------------------- + + /** + * @see #getStack + */ + private Deque stack = new ArrayDeque(); + + private transient TypeUtil vertexTypeDecl = null; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new depth-first iterator for the specified graph. + * + * @param g the graph to be iterated. + */ + public DepthFirstIterator(Graph g) + { + this(g, null); + } + + /** + * Creates a new depth-first iterator for the specified graph. Iteration + * will start at the specified start vertex and will be limited to the + * connected component that includes that vertex. If the specified start + * vertex is null, iteration will start at an arbitrary vertex + * and will not be limited, that is, will be able to traverse all the graph. + * + * @param g the graph to be iterated. + * @param startVertex the vertex iteration to be started. + */ + public DepthFirstIterator(Graph g, V startVertex) + { + super(g, startVertex); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see CrossComponentIterator#isConnectedComponentExhausted() + */ + protected boolean isConnectedComponentExhausted() + { + for (;;) { + if (stack.isEmpty()) { + return true; + } + if (stack.getLast() != SENTINEL) { + // Found a non-sentinel. + return false; + } + + // Found a sentinel: pop it, record the finish time, + // and then loop to check the rest of the stack. + + // Pop null we peeked at above. + stack.removeLast(); + + // This will pop corresponding vertex to be recorded as finished. + recordFinish(); + } + } + + /** + * @see CrossComponentIterator#encounterVertex(Object, Object) + */ + protected void encounterVertex(V vertex, E edge) + { + putSeenData(vertex, VisitColor.WHITE); + stack.addLast(vertex); + } + + /** + * @see CrossComponentIterator#encounterVertexAgain(Object, Object) + */ + protected void encounterVertexAgain(V vertex, E edge) + { + VisitColor color = getSeenData(vertex); + if (color != VisitColor.WHITE) { + // We've already visited this vertex; no need to mess with the + // stack (either it's BLACK and not there at all, or it's GRAY + // and therefore just a sentinel). + return; + } + + // Since we've encountered it before, and it's still WHITE, it + // *must* be on the stack. Use removeLastOccurrence on the + // assumption that for typical topologies and traversals, + // it's likely to be nearer the top of the stack than + // the bottom of the stack. + boolean found = stack.removeLastOccurrence(vertex); + assert (found); + stack.addLast(vertex); + } + + /** + * @see CrossComponentIterator#provideNextVertex() + */ + protected V provideNextVertex() + { + V v; + for (;;) { + Object o = stack.removeLast(); + if (o == SENTINEL) { + // This is a finish-time sentinel we previously pushed. + recordFinish(); + // Now carry on with another pop until we find a non-sentinel + } else { + // Got a real vertex to start working on + v = TypeUtil.uncheckedCast(o, vertexTypeDecl); + break; + } + } + + // Push a sentinel for v onto the stack so that we'll know + // when we're done with it. + stack.addLast(v); + stack.addLast(SENTINEL); + putSeenData(v, VisitColor.GRAY); + return v; + } + + private void recordFinish() + { + V v = TypeUtil.uncheckedCast(stack.removeLast(), vertexTypeDecl); + putSeenData(v, VisitColor.BLACK); + finishVertex(v); + } + + /** + * Retrieves the LIFO stack of vertices which have been encountered but not + * yet visited (WHITE). This stack also contains sentinel entries + * representing vertices which have been visited but are still GRAY. A + * sentinel entry is a sequence (v, SENTINEL), whereas a non-sentinel entry + * is just (v). + * + * @return stack + */ + public Deque getStack() + { + return stack; + } +} + +// End DepthFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/GraphIterator.java b/wdl/org/jgrapht/traverse/GraphIterator.java new file mode 100644 index 0000000..2cfa98f --- /dev/null +++ b/wdl/org/jgrapht/traverse/GraphIterator.java @@ -0,0 +1,114 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------ + * GraphIterator.java + * ------------------ + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): Christian Hammer + * + * $Id$ + * + * Changes + * ------- + * 31-Jul-2003 : Initial revision (BN); + * 11-Aug-2003 : Adaptation to new event model (BN); + * 04-May-2004 : Made generic (CH) + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.event.*; + + +/** + * A graph iterator. + * + * @author Barak Naveh + * @since Jul 31, 2003 + */ +public interface GraphIterator + extends Iterator +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Test whether this iterator is set to traverse the grpah across connected + * components. + * + * @return true if traverses across connected components, + * otherwise false. + */ + public boolean isCrossComponentTraversal(); + + /** + * Sets a value the reuseEvents flag. If the + * reuseEvents flag is set to true this class will reuse + * previously fired events and will not create a new object for each event. + * This option increases performance but should be used with care, + * especially in multithreaded environment. + * + * @param reuseEvents whether to reuse previously fired event objects + * instead of creating a new event object for each event. + */ + public void setReuseEvents(boolean reuseEvents); + + /** + * Tests whether the reuseEvents flag is set. If the flag is + * set to true this class will reuse previously fired events + * and will not create a new object for each event. This option increases + * performance but should be used with care, especially in multithreaded + * environment. + * + * @return the value of the reuseEvents flag. + */ + public boolean isReuseEvents(); + + /** + * Adds the specified traversal listener to this iterator. + * + * @param l the traversal listener to be added. + */ + public void addTraversalListener(TraversalListener l); + + /** + * Unsupported. + * + * @throws UnsupportedOperationException + */ + public void remove(); + + /** + * Removes the specified traversal listener from this iterator. + * + * @param l the traversal listener to be removed. + */ + public void removeTraversalListener(TraversalListener l); +} + +// End GraphIterator.java diff --git a/wdl/org/jgrapht/traverse/TopologicalOrderIterator.java b/wdl/org/jgrapht/traverse/TopologicalOrderIterator.java new file mode 100644 index 0000000..4365373 --- /dev/null +++ b/wdl/org/jgrapht/traverse/TopologicalOrderIterator.java @@ -0,0 +1,277 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------------------- + * TopologicalOrderIterator.java + * ----------------------------- + * (C) Copyright 2004-2008, by Marden Neubert and Contributors. + * + * Original Author: Marden Neubert + * Contributor(s): Barak Naveh, John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 17-Dec-2004 : Initial revision (MN); + * 25-Apr-2005 : Fixes for start vertex order (JVS); + * 06-Jun-2005 : Made generic (CH); + * + */ +package org.jgrapht.traverse; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.util.*; + + +/** + * Implements topological order traversal for a directed acyclic graph. A + * topological sort is a permutation p of the vertices of a graph such + * that an edge (i,j) implies that i appears before j + * in p (Skiena 1990, p. 208). See also + * http://mathworld.wolfram.com/TopologicalSort.html. + * + *

    See "Algorithms in Java, Third Edition, Part 5: Graph Algorithms" by + * Robert Sedgewick and "Data Structures and Algorithms with Object-Oriented + * Design Patterns in Java" by Bruno R. Preiss for implementation alternatives. + * The latter can be found online at + * http://www.brpreiss.com/books/opus5/

    + * + *

    For this iterator to work correctly the graph must be acyclic, and must + * not be modified during iteration. Currently there are no means to ensure + * that, nor to fail-fast; the results with cyclic input (including self-loops) + * or concurrent modifications are undefined. To precheck a graph for cycles, + * consider using {@link org.jgrapht.alg.CycleDetector} or {@link + * org.jgrapht.alg.StrongConnectivityInspector}.

    + * + * @author Marden Neubert + * @since Dec 18, 2004 + */ +public class TopologicalOrderIterator + extends CrossComponentIterator +{ + //~ Instance fields -------------------------------------------------------- + + private Queue queue; + private Map inDegreeMap; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new topological order iterator over the directed graph + * specified, with arbitrary tie-breaking in case of partial order. + * Traversal will start at one of the graph's sources. See the + * definition of source at + * http://mathworld.wolfram.com/Source.html. + * + * @param dg the directed graph to be iterated. + */ + public TopologicalOrderIterator(DirectedGraph dg) + { + this(dg, new LinkedListQueue()); + } + + /** + * Creates a new topological order iterator over the directed graph + * specified, with a user-supplied queue implementation to allow customized + * control over tie-breaking in case of partial order. Traversal will start + * at one of the graph's sources. See the definition of source at + * http://mathworld.wolfram.com/Source.html. + * + * @param dg the directed graph to be iterated. + * @param queue queue to use for tie-break in case of partial order (e.g. a + * PriorityQueue can be used to break ties according to vertex priority); + * must be initially empty + */ + public TopologicalOrderIterator(DirectedGraph dg, Queue queue) + { + this(dg, queue, new HashMap()); + } + + // NOTE: This is a hack to deal with the fact that CrossComponentIterator + // needs to know the start vertex in its constructor + private TopologicalOrderIterator( + DirectedGraph dg, + Queue queue, + Map inDegreeMap) + { + this(dg, initialize(dg, queue, inDegreeMap)); + this.queue = queue; + this.inDegreeMap = inDegreeMap; + + // empty queue for non-empty graph would indicate presence of + // cycles (no roots found) + assert dg.vertexSet().isEmpty() || !queue.isEmpty(); + } + + // NOTE: This is intentionally private, because starting the sort "in the + // middle" doesn't make sense. + private TopologicalOrderIterator(DirectedGraph dg, V start) + { + super(dg, start); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * @see CrossComponentIterator#isConnectedComponentExhausted() + */ + protected boolean isConnectedComponentExhausted() + { + // FIXME jvs 25-Apr-2005: This isn't correct for a graph with more than + // one component. We will actually exhaust a connected component + // before the queue is empty, because initialize adds roots from all + // components to the queue. + return queue.isEmpty(); + } + + /** + * @see CrossComponentIterator#encounterVertex(Object, Object) + */ + protected void encounterVertex(V vertex, E edge) + { + putSeenData(vertex, null); + decrementInDegree(vertex); + } + + /** + * @see CrossComponentIterator#encounterVertexAgain(Object, Object) + */ + protected void encounterVertexAgain(V vertex, E edge) + { + decrementInDegree(vertex); + } + + /** + * @see CrossComponentIterator#provideNextVertex() + */ + protected V provideNextVertex() + { + return queue.remove(); + } + + /** + * Decrements the in-degree of a vertex. + * + * @param vertex the vertex whose in-degree will be decremented. + */ + private void decrementInDegree(V vertex) + { + ModifiableInteger inDegree = inDegreeMap.get(vertex); + + if (inDegree.value > 0) { + inDegree.value--; + + if (inDegree.value == 0) { + queue.offer(vertex); + } + } + } + + /** + * Initializes the internal traversal object structure. Sets up the internal + * queue with the directed graph vertices and creates the control structure + * for the in-degrees. + * + * @param dg the directed graph to be iterated. + * @param queue initializer for queue + * @param inDegreeMap initializer for inDegreeMap + * + * @return start vertex + */ + private static V initialize( + DirectedGraph dg, + Queue queue, + Map inDegreeMap) + { + for (Iterator i = dg.vertexSet().iterator(); i.hasNext();) { + V vertex = i.next(); + + int inDegree = dg.inDegreeOf(vertex); + inDegreeMap.put(vertex, new ModifiableInteger(inDegree)); + + if (inDegree == 0) { + queue.offer(vertex); + } + } + + if (queue.isEmpty()) { + return null; + } else { + return queue.peek(); + } + } + + //~ Inner Classes ---------------------------------------------------------- + + // NOTE jvs 22-Dec-2006: For JDK1.4-compatibility, we can't assume + // that LinkedList implements Queue, since that wasn't introduced + // until JDK1.5, so use an adapter here. Move this to + // top-level in org.jgrapht.util if anyone else needs it. + private static class LinkedListQueue + extends LinkedList + implements Queue + { + private static final long serialVersionUID = 4217659843476891334L; + + public T element() + { + return getFirst(); + } + + public boolean offer(T o) + { + return add(o); + } + + public T peek() + { + if (isEmpty()) { + return null; + } + return getFirst(); + } + + public T poll() + { + if (isEmpty()) { + return null; + } + return removeFirst(); + } + + public T remove() + { + return removeFirst(); + } + } +} + +// End TopologicalOrderIterator.java diff --git a/wdl/org/jgrapht/traverse/package.html b/wdl/org/jgrapht/traverse/package.html new file mode 100644 index 0000000..145444a --- /dev/null +++ b/wdl/org/jgrapht/traverse/package.html @@ -0,0 +1,6 @@ + + + +Graph traversal means. + + \ No newline at end of file diff --git a/wdl/org/jgrapht/util/ArrayUnenforcedSet.java b/wdl/org/jgrapht/util/ArrayUnenforcedSet.java new file mode 100644 index 0000000..b9387fe --- /dev/null +++ b/wdl/org/jgrapht/util/ArrayUnenforcedSet.java @@ -0,0 +1,112 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * ArrayUnenforcedSet.java + * ----------------- + * (C) Copyright 2006-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 07-May-2006 : Initial version (JVS); + */ +package org.jgrapht.util; + +import java.util.*; + + +/** + * Helper for efficiently representing small sets whose elements are known to be + * unique by construction, implying we don't need to enforce the uniqueness + * property in the data structure itself. Use with caution. + * + *

    Note that for equals/hashCode, the class implements the Set behavior + * (unordered), not the list behavior (ordered); the fact that it subclasses + * ArrayList should be considered an implementation detail. + * + * @author John V. Sichi + */ +public class ArrayUnenforcedSet + extends ArrayList + implements Set +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = -7413250161201811238L; + + //~ Constructors ----------------------------------------------------------- + + public ArrayUnenforcedSet() + { + super(); + } + + public ArrayUnenforcedSet(Collection c) + { + super(c); + } + + public ArrayUnenforcedSet(int n) + { + super(n); + } + + //~ Methods ---------------------------------------------------------------- + + public boolean equals(Object o) + { + return new SetForEquality().equals(o); + } + + public int hashCode() + { + return new SetForEquality().hashCode(); + } + + //~ Inner Classes ---------------------------------------------------------- + + /** + * Multiple inheritance helper. + */ + private class SetForEquality + extends AbstractSet + { + public Iterator iterator() + { + return ArrayUnenforcedSet.this.iterator(); + } + + public int size() + { + return ArrayUnenforcedSet.this.size(); + } + } +} + +// End ArrayUnenforcedSet.java diff --git a/wdl/org/jgrapht/util/FibonacciHeap.java b/wdl/org/jgrapht/util/FibonacciHeap.java new file mode 100644 index 0000000..569ed8c --- /dev/null +++ b/wdl/org/jgrapht/util/FibonacciHeap.java @@ -0,0 +1,611 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * FibonnaciHeap.java + * -------------------------- + * (C) Copyright 1999-2003, by Nathan Fiedler and Contributors. + * + * Original Author: Nathan Fiedler + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS); + * + * Name Date Description + * ---- ---- ----------- + * nf 08/31/97 Initial version + * nf 09/07/97 Removed FibHeapData interface + * nf 01/20/01 Added synchronization + * nf 01/21/01 Made Node an inner class + * nf 01/05/02 Added clear(), renamed empty() to + * isEmpty(), and renamed printHeap() + * to toString() + * nf 01/06/02 Removed all synchronization + * + */ +package org.jgrapht.util; + +import java.util.*; + + +/** + * This class implements a Fibonacci heap data structure. Much of the code in + * this class is based on the algorithms in the "Introduction to Algorithms"by + * Cormen, Leiserson, and Rivest in Chapter 21. The amortized running time of + * most of these methods is O(1), making it a very fast data structure. Several + * have an actual running time of O(1). removeMin() and delete() have O(log n) + * amortized running times because they do the heap consolidation. If you + * attempt to store nodes in this heap with key values of -Infinity + * (Double.NEGATIVE_INFINITY) the delete() operation may fail to + * remove the correct element. + * + *

    Note that this implementation is not synchronized. If multiple + * threads access a set concurrently, and at least one of the threads modifies + * the set, it must be synchronized externally. This is typically + * accomplished by synchronizing on some object that naturally encapsulates the + * set.

    + * + *

    This class was originally developed by Nathan Fiedler for the GraphMaker + * project. It was imported to JGraphT with permission, courtesy of Nathan + * Fiedler.

    + * + * @author Nathan Fiedler + */ +public class FibonacciHeap +{ + //~ Static fields/initializers --------------------------------------------- + + private static final double oneOverLogPhi = + 1.0 / Math.log((1.0 + Math.sqrt(5.0)) / 2.0); + + //~ Instance fields -------------------------------------------------------- + + /** + * Points to the minimum node in the heap. + */ + private FibonacciHeapNode minNode; + + /** + * Number of nodes in the heap. + */ + private int nNodes; + + //~ Constructors ----------------------------------------------------------- + + /** + * Constructs a FibonacciHeap object that contains no elements. + */ + public FibonacciHeap() + { + } // FibonacciHeap + + //~ Methods ---------------------------------------------------------------- + + /** + * Tests if the Fibonacci heap is empty or not. Returns true if the heap is + * empty, false otherwise. + * + *

    Running time: O(1) actual

    + * + * @return true if the heap is empty, false otherwise + */ + public boolean isEmpty() + { + return minNode == null; + } + + // isEmpty + + /** + * Removes all elements from this heap. + */ + public void clear() + { + minNode = null; + nNodes = 0; + } + + // clear + + /** + * Decreases the key value for a heap node, given the new value to take on. + * The structure of the heap may be changed and will not be consolidated. + * + *

    Running time: O(1) amortized

    + * + * @param x node to decrease the key of + * @param k new key value for node x + * + * @exception IllegalArgumentException Thrown if k is larger than x.key + * value. + */ + public void decreaseKey(FibonacciHeapNode x, double k) + { + if (k > x.key) { + throw new IllegalArgumentException( + "decreaseKey() got larger key value"); + } + + x.key = k; + + FibonacciHeapNode y = x.parent; + + if ((y != null) && (x.key < y.key)) { + cut(x, y); + cascadingCut(y); + } + + if (x.key < minNode.key) { + minNode = x; + } + } + + // decreaseKey + + /** + * Deletes a node from the heap given the reference to the node. The trees + * in the heap will be consolidated, if necessary. This operation may fail + * to remove the correct element if there are nodes with key value + * -Infinity. + * + *

    Running time: O(log n) amortized

    + * + * @param x node to remove from heap + */ + public void delete(FibonacciHeapNode x) + { + // make x as small as possible + decreaseKey(x, Double.NEGATIVE_INFINITY); + + // remove the smallest, which decreases n also + removeMin(); + } + + // delete + + /** + * Inserts a new data element into the heap. No heap consolidation is + * performed at this time, the new node is simply inserted into the root + * list of this heap. + * + *

    Running time: O(1) actual

    + * + * @param node new node to insert into heap + * @param key key value associated with data object + */ + public void insert(FibonacciHeapNode node, double key) + { + node.key = key; + + // concatenate node into min list + if (minNode != null) { + node.left = minNode; + node.right = minNode.right; + minNode.right = node; + node.right.left = node; + + if (key < minNode.key) { + minNode = node; + } + } else { + minNode = node; + } + + nNodes++; + } + + // insert + + /** + * Returns the smallest element in the heap. This smallest element is the + * one with the minimum key value. + * + *

    Running time: O(1) actual

    + * + * @return heap node with the smallest key + */ + public FibonacciHeapNode min() + { + return minNode; + } + + // min + + /** + * Removes the smallest element from the heap. This will cause the trees in + * the heap to be consolidated, if necessary. + * + *

    Running time: O(log n) amortized

    + * + * @return node with the smallest key + */ + public FibonacciHeapNode removeMin() + { + FibonacciHeapNode z = minNode; + + if (z != null) { + int numKids = z.degree; + FibonacciHeapNode x = z.child; + FibonacciHeapNode tempRight; + + // for each child of z do... + while (numKids > 0) { + tempRight = x.right; + + // remove x from child list + x.left.right = x.right; + x.right.left = x.left; + + // add x to root list of heap + x.left = minNode; + x.right = minNode.right; + minNode.right = x; + x.right.left = x; + + // set parent[x] to null + x.parent = null; + x = tempRight; + numKids--; + } + + // remove z from root list of heap + z.left.right = z.right; + z.right.left = z.left; + + if (z == z.right) { + minNode = null; + } else { + minNode = z.right; + consolidate(); + } + + // decrement size of heap + nNodes--; + } + + return z; + } + + // removeMin + + /** + * Returns the size of the heap which is measured in the number of elements + * contained in the heap. + * + *

    Running time: O(1) actual

    + * + * @return number of elements in the heap + */ + public int size() + { + return nNodes; + } + + // size + + /** + * Joins two Fibonacci heaps into a new one. No heap consolidation is + * performed at this time. The two root lists are simply joined together. + * + *

    Running time: O(1) actual

    + * + * @param h1 first heap + * @param h2 second heap + * + * @return new heap containing h1 and h2 + */ + public static FibonacciHeap union( + FibonacciHeap h1, + FibonacciHeap h2) + { + FibonacciHeap h = new FibonacciHeap(); + + if ((h1 != null) && (h2 != null)) { + h.minNode = h1.minNode; + + if (h.minNode != null) { + if (h2.minNode != null) { + h.minNode.right.left = h2.minNode.left; + h2.minNode.left.right = h.minNode.right; + h.minNode.right = h2.minNode; + h2.minNode.left = h.minNode; + + if (h2.minNode.key < h1.minNode.key) { + h.minNode = h2.minNode; + } + } + } else { + h.minNode = h2.minNode; + } + + h.nNodes = h1.nNodes + h2.nNodes; + } + + return h; + } + + // union + + /** + * Creates a String representation of this Fibonacci heap. + * + * @return String of this. + */ + public String toString() + { + if (minNode == null) { + return "FibonacciHeap=[]"; + } + + // create a new stack and put root on it + Stack> stack = new Stack>(); + stack.push(minNode); + + StringBuffer buf = new StringBuffer(512); + buf.append("FibonacciHeap=["); + + // do a simple breadth-first traversal on the tree + while (!stack.empty()) { + FibonacciHeapNode curr = stack.pop(); + buf.append(curr); + buf.append(", "); + + if (curr.child != null) { + stack.push(curr.child); + } + + FibonacciHeapNode start = curr; + curr = curr.right; + + while (curr != start) { + buf.append(curr); + buf.append(", "); + + if (curr.child != null) { + stack.push(curr.child); + } + + curr = curr.right; + } + } + + buf.append(']'); + + return buf.toString(); + } + + // toString + + /** + * Performs a cascading cut operation. This cuts y from its parent and then + * does the same for its parent, and so on up the tree. + * + *

    Running time: O(log n); O(1) excluding the recursion

    + * + * @param y node to perform cascading cut on + */ + protected void cascadingCut(FibonacciHeapNode y) + { + FibonacciHeapNode z = y.parent; + + // if there's a parent... + if (z != null) { + // if y is unmarked, set it marked + if (!y.mark) { + y.mark = true; + } else { + // it's marked, cut it from parent + cut(y, z); + + // cut its parent as well + cascadingCut(z); + } + } + } + + // cascadingCut + + protected void consolidate() + { + int arraySize = + ((int) Math.floor(Math.log(nNodes) * oneOverLogPhi)) + 1; + + List> array = + new ArrayList>(arraySize); + + // Initialize degree array + for (int i = 0; i < arraySize; i++) { + array.add(null); + } + + // Find the number of root nodes. + int numRoots = 0; + FibonacciHeapNode x = minNode; + + if (x != null) { + numRoots++; + x = x.right; + + while (x != minNode) { + numRoots++; + x = x.right; + } + } + + // For each node in root list do... + while (numRoots > 0) { + // Access this node's degree.. + int d = x.degree; + FibonacciHeapNode next = x.right; + + // ..and see if there's another of the same degree. + for (;;) { + FibonacciHeapNode y = array.get(d); + if (y == null) { + // Nope. + break; + } + + // There is, make one of the nodes a child of the other. + // Do this based on the key value. + if (x.key > y.key) { + FibonacciHeapNode temp = y; + y = x; + x = temp; + } + + // FibonacciHeapNode y disappears from root list. + link(y, x); + + // We've handled this degree, go to next one. + array.set(d, null); + d++; + } + + // Save this node for later when we might encounter another + // of the same degree. + array.set(d, x); + + // Move forward through list. + x = next; + numRoots--; + } + + // Set min to null (effectively losing the root list) and + // reconstruct the root list from the array entries in array[]. + minNode = null; + + for (int i = 0; i < arraySize; i++) { + FibonacciHeapNode y = array.get(i); + if (y == null) { + continue; + } + + // We've got a live one, add it to root list. + if (minNode != null) { + // First remove node from root list. + y.left.right = y.right; + y.right.left = y.left; + + // Now add to root list, again. + y.left = minNode; + y.right = minNode.right; + minNode.right = y; + y.right.left = y; + + // Check if this is a new min. + if (y.key < minNode.key) { + minNode = y; + } + } else { + minNode = y; + } + } + } + + // consolidate + + /** + * The reverse of the link operation: removes x from the child list of y. + * This method assumes that min is non-null. + * + *

    Running time: O(1)

    + * + * @param x child of y to be removed from y's child list + * @param y parent of x about to lose a child + */ + protected void cut(FibonacciHeapNode x, FibonacciHeapNode y) + { + // remove x from childlist of y and decrement degree[y] + x.left.right = x.right; + x.right.left = x.left; + y.degree--; + + // reset y.child if necessary + if (y.child == x) { + y.child = x.right; + } + + if (y.degree == 0) { + y.child = null; + } + + // add x to root list of heap + x.left = minNode; + x.right = minNode.right; + minNode.right = x; + x.right.left = x; + + // set parent[x] to nil + x.parent = null; + + // set mark[x] to false + x.mark = false; + } + + // cut + + /** + * Make node y a child of node x. + * + *

    Running time: O(1) actual

    + * + * @param y node to become child + * @param x node to become parent + */ + protected void link(FibonacciHeapNode y, FibonacciHeapNode x) + { + // remove y from root list of heap + y.left.right = y.right; + y.right.left = y.left; + + // make y a child of x + y.parent = x; + + if (x.child == null) { + x.child = y; + y.right = y; + y.left = y; + } else { + y.left = x.child; + y.right = x.child.right; + x.child.right = y; + y.right.left = y; + } + + // increase degree[x] + x.degree++; + + // set mark[y] false + y.mark = false; + } + + // link +} + +// FibonacciHeap diff --git a/wdl/org/jgrapht/util/FibonacciHeapNode.java b/wdl/org/jgrapht/util/FibonacciHeapNode.java new file mode 100644 index 0000000..2a54150 --- /dev/null +++ b/wdl/org/jgrapht/util/FibonacciHeapNode.java @@ -0,0 +1,154 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* -------------------------- + * FibonnaciHeapNode.java + * -------------------------- + * (C) Copyright 1999-2008, by Nathan Fiedler and Contributors. + * + * Original Author: Nathan Fiedler + * Contributor(s): John V. Sichi + * + * $Id$ + * + * Changes + * ------- + * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS); + * + * Name Date Description + * ---- ---- ----------- + * nf 08/31/97 Initial version + * nf 09/07/97 Removed FibHeapData interface + * nf 01/20/01 Added synchronization + * nf 01/21/01 Made Node an inner class + * nf 01/05/02 Added clear(), renamed empty() to + * isEmpty(), and renamed printHeap() + * to toString() + * nf 01/06/02 Removed all synchronization + * JVS 06/24/06 Generics + * + */ +package org.jgrapht.util; + +/** + * Implements a node of the Fibonacci heap. It holds the information necessary + * for maintaining the structure of the heap. It also holds the reference to the + * key value (which is used to determine the heap structure). + * + * @author Nathan Fiedler + */ +public class FibonacciHeapNode +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Node data. + */ + T data; + + /** + * first child node + */ + FibonacciHeapNode child; + + /** + * left sibling node + */ + FibonacciHeapNode left; + + /** + * parent node + */ + FibonacciHeapNode parent; + + /** + * right sibling node + */ + FibonacciHeapNode right; + + /** + * true if this node has had a child removed since this node was added to + * its parent + */ + boolean mark; + + /** + * key value for this node + */ + double key; + + /** + * number of children of this node (does not count grandchildren) + */ + int degree; + + //~ Constructors ----------------------------------------------------------- + + /** + * Default constructor. Initializes the right and left pointers, making this + * a circular doubly-linked list. + * + * @param data data for this node + */ + public FibonacciHeapNode(T data) + { + right = this; + left = this; + this.data = data; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Obtain the key for this node. + * + * @return the key + */ + public final double getKey() + { + return key; + } + + /** + * Obtain the data for this node. + */ + public final T getData() + { + return data; + } + + /** + * Return the string representation of this object. + * + * @return string representing this object + */ + public String toString() + { + return Double.toString(key); + } + + // toString +} + +// End FibonacciHeapNode.java diff --git a/wdl/org/jgrapht/util/MathUtil.java b/wdl/org/jgrapht/util/MathUtil.java new file mode 100644 index 0000000..87620d8 --- /dev/null +++ b/wdl/org/jgrapht/util/MathUtil.java @@ -0,0 +1,61 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * MathUtil.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.util; + +/** + * Math Utilities. Currently contains the following: + *
  • factorial(int N) - caclulate the factorial of N (aka N!) + * + * @author Assaf + * @since May 30, 2005 + */ +public class MathUtil +{ + //~ Methods ---------------------------------------------------------------- + + public static long factorial(int N) + { + long multi = 1; + for (int i = 1; i <= N; i++) { + multi = multi * i; + } + return multi; + } +} + +// End MathUtil.java diff --git a/wdl/org/jgrapht/util/ModifiableInteger.java b/wdl/org/jgrapht/util/ModifiableInteger.java new file mode 100644 index 0000000..041c6aa --- /dev/null +++ b/wdl/org/jgrapht/util/ModifiableInteger.java @@ -0,0 +1,261 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ---------------------- + * ModifiableInteger.java + * ---------------------- + * + * (C) Copyright 2002-2004, by Barak Naveh and Contributors. + * + * Original Author: Barak Naveh + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 2004-05-27 : Initial version (BN); + * + */ +package org.jgrapht.util; + +/** + * The ModifiableInteger class wraps a value of the primitive type + * int in an object, similarly to {@link java.lang.Integer}. An + * object of type ModifiableInteger contains a single field whose + * type is int. + * + *

    Unlike java.lang.Integer, the int value which the + * ModifiableInteger represents can be modified. It becomes useful when used + * together with the collection framework. For example, if you want to have a + * {@link java.util.List} of counters. You could use Integer but + * that would have became wasteful and inefficient if you frequently had to + * update the counters.

    + * + *

    WARNING: Because instances of this class are mutable, great care must be + * exercised if used as keys of a {@link java.util.Map} or as values in a {@link + * java.util.Set} in a manner that affects equals comparisons while the + * instances are keys in the map (or values in the set). For more see + * documentation of Map and Set.

    + * + * @author Barak Naveh + * @since May 27, 2004 + */ +public class ModifiableInteger + extends Number + implements Comparable +{ + //~ Static fields/initializers --------------------------------------------- + + private static final long serialVersionUID = 3618698612851422261L; + + //~ Instance fields -------------------------------------------------------- + + /** + * The int value represented by this ModifiableInteger. + */ + public int value; + + //~ Constructors ----------------------------------------------------------- + + /** + * !!! DON'T USE - Use the {@link #ModifiableInteger(int)} constructor + * instead !!! + * + *

    This constructor is for the use of java.beans.XMLDecoder + * deserialization. The constructor is marked as 'deprecated' to indicate to + * the programmer against using it by mistake.

    + * + * @deprecated not really deprecated, just marked so to avoid mistaken use. + */ + @Deprecated public ModifiableInteger() + { + } + + /** + * Constructs a newly allocated ModifiableInteger object that + * represents the specified int value. + * + * @param value the value to be represented by the + * ModifiableInteger object. + */ + public ModifiableInteger(int value) + { + this.value = value; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Sets a new value for this modifiable integer. + * + * @param value the new value to set. + */ + public void setValue(int value) + { + this.value = value; + } + + /** + * Returns the value of this object, similarly to {@link #intValue()}. This + * getter is NOT redundant. It is used for serialization by + * java.beans.XMLEncoder. + * + * @return the value. + */ + public int getValue() + { + return this.value; + } + + /** + * Adds one to the value of this modifiable integer. + */ + public void increment() + { + this.value++; + } + + /** + * Subtracts one from the value of this modifiable integer. + */ + public void decrement() + { + this.value--; + } + + /** + * Compares two ModifiableInteger objects numerically. + * + * @param anotherInteger the ModifiableInteger to be compared. + * + * @return the value 0 if this ModifiableInteger + * is equal to the argument ModifiableInteger; a value less + * than 0 if this ModifiableInteger is numerically + * less than the argument ModifiableInteger; and a value + * greater than 0 if this ModifiableInteger is + * numerically greater than the argument ModifiableInteger + * (signed comparison). + */ + public int compareTo(ModifiableInteger anotherInteger) + { + int thisVal = this.value; + int anotherVal = anotherInteger.value; + + return (thisVal < anotherVal) ? -1 : ((thisVal == anotherVal) ? 0 : 1); + } + + /** + * @see Number#doubleValue() + */ + public double doubleValue() + { + return this.value; + } + + /** + * Compares this object to the specified object. The result is + * true if and only if the argument is not null and is + * an ModifiableInteger object that contains the same + * int value as this object. + * + * @param o the object to compare with. + * + * @return true if the objects are the same; false + * otherwise. + */ + public boolean equals(Object o) + { + if (o instanceof ModifiableInteger) { + return this.value == ((ModifiableInteger) o).value; + } + + return false; + } + + /** + * @see Number#floatValue() + */ + public float floatValue() + { + return this.value; + } + + /** + * Returns a hash code for this ModifiableInteger. + * + * @return a hash code value for this object, equal to the primitive + * int value represented by this ModifiableInteger + * object. + */ + public int hashCode() + { + return this.value; + } + + /** + * @see Number#intValue() + */ + public int intValue() + { + return this.value; + } + + /** + * @see Number#longValue() + */ + public long longValue() + { + return this.value; + } + + /** + * Returns an Integer object representing this + * ModifiableInteger's value. + * + * @return an Integer representation of the value of this + * object. + */ + public Integer toInteger() + { + return Integer.valueOf(this.value); + } + + /** + * Returns a String object representing this + * ModifiableInteger's value. The value is converted to signed + * decimal representation and returned as a string, exactly as if the + * integer value were given as an argument to the {@link + * java.lang.Integer#toString(int)} method. + * + * @return a string representation of the value of this object in + * base 10. + */ + public String toString() + { + return String.valueOf(this.value); + } +} + +// End ModifiableInteger.java diff --git a/wdl/org/jgrapht/util/PrefetchIterator.java b/wdl/org/jgrapht/util/PrefetchIterator.java new file mode 100644 index 0000000..e37fde0 --- /dev/null +++ b/wdl/org/jgrapht/util/PrefetchIterator.java @@ -0,0 +1,223 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * PrefetchIterator.java + * ----------------- + * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. + * + * Original Author: Assaf Lehr + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + */ +package org.jgrapht.util; + +import java.util.*; + + +/** + * Utility class to help implement an iterator/enumerator in which the hasNext() + * method needs to calculate the next elements ahead of time. + * + *

    Many classes which implement an iterator face a common problem: if there + * is no easy way to calculate hasNext() other than to call getNext(), then they + * save the result for fetching in the next call to getNext(). This utility + * helps in doing just that. + * + *

    Usage: The new iterator class will hold this class as a member + * variable and forward the hasNext() and next() to it. When creating an + * instance of this class, you supply it with a functor that is doing the real + * job of calculating the next element. + * + *

    
    +    //This class supllies enumeration of integer till 100.
    +    public class IteratorExample implements Enumeration{
    +    private int counter=0;
    +    private PrefetchIterator nextSupplier;
    +
    +        IteratorExample()
    +        {
    +            nextSupplier = new PrefetchIterator(new PrefetchIterator.NextElementFunctor(){
    +
    +                public Object nextElement() throws NoSuchElementException {
    +                    counter++;
    +                    if (counter>=100)
    +                        throw new NoSuchElementException();
    +                    else
    +                        return new Integer(counter);
    +                }
    +
    +            });
    +        }
    +        //forwarding to nextSupplier and return its returned value
    +        public boolean hasMoreElements() {
    +            return this.nextSupplier.hasMoreElements();
    +        }
    +    //  forwarding to nextSupplier and return its returned value
    +        public Object nextElement() {
    +            return this.nextSupplier.nextElement();
    +        }
    +  }
    + * + * + * @author Assaf_Lehr + */ +public class PrefetchIterator + implements Iterator, + Enumeration +{ + //~ Instance fields -------------------------------------------------------- + + private NextElementFunctor innerEnum; + private E getNextLastResult; + private boolean isGetNextLastResultUpToDate = false; + private boolean endOfEnumerationReached = false; + private boolean flagIsEnumerationStartedEmpty = true; + private int innerFunctorUsageCounter = 0; + + //~ Constructors ----------------------------------------------------------- + + public PrefetchIterator(NextElementFunctor aEnum) + { + innerEnum = aEnum; + } + + //~ Methods ---------------------------------------------------------------- + + /** + * Serves as one contact place to the functor; all must use it and not + * directly the NextElementFunctor. + */ + private E getNextElementFromInnerFunctor() + { + innerFunctorUsageCounter++; + E result = this.innerEnum.nextElement(); + + // if we got here , an exception was not thrown, so at least + // one time a good value returned + flagIsEnumerationStartedEmpty = false; + return result; + } + + /** + * 1. Retrieves the saved value or calculates it if it does not exist 2. + * Changes isGetNextLastResultUpToDate to false. (Because it does not save + * the NEXT element now; it saves the current one!) + */ + public E nextElement() + { + E result = null; + if (this.isGetNextLastResultUpToDate) { + result = this.getNextLastResult; + } else { + result = getNextElementFromInnerFunctor(); + } + + this.isGetNextLastResultUpToDate = false; + return result; + } + + /** + * If (isGetNextLastResultUpToDate==true) returns true else 1. calculates + * getNext() and saves it 2. sets isGetNextLastResultUpToDate to true. + */ + public boolean hasMoreElements() + { + if (endOfEnumerationReached) { + return false; + } + + if (isGetNextLastResultUpToDate) { + return true; + } else { + try { + this.getNextLastResult = getNextElementFromInnerFunctor(); + this.isGetNextLastResultUpToDate = true; + return true; + } catch (NoSuchElementException noSuchE) { + endOfEnumerationReached = true; + return false; + } + } // else + } // method + + /** + * Tests whether the enumeration started as an empty one. It does not matter + * if it hasMoreElements() now, only at initialization time. Efficiency: if + * nextElements(), hasMoreElements() were never used, it activates the + * hasMoreElements() once. Else it is immediately(O(1)) + */ + public boolean isEnumerationStartedEmpty() + { + if (this.innerFunctorUsageCounter == 0) { + if (hasMoreElements()) { + return false; + } else { + return true; + } + } else // it is not the first time , so use the saved value + // which was initilaizeed during a call to + // getNextElementFromInnerFunctor + { + return flagIsEnumerationStartedEmpty; + } + } + + public boolean hasNext() + { + return this.hasMoreElements(); + } + + public E next() + { + return this.nextElement(); + } + + /** + * Always throws UnsupportedOperationException. + */ + public void remove() + throws UnsupportedOperationException + { + throw new UnsupportedOperationException(); + } + + //~ Inner Interfaces ------------------------------------------------------- + + public interface NextElementFunctor + { + /** + * You must implement that NoSuchElementException is thrown on + * nextElement() if it is out of bound. + */ + public EE nextElement() + throws NoSuchElementException; + } +} + +// End PrefetchIterator.java diff --git a/wdl/org/jgrapht/util/TypeUtil.java b/wdl/org/jgrapht/util/TypeUtil.java new file mode 100644 index 0000000..81f2937 --- /dev/null +++ b/wdl/org/jgrapht/util/TypeUtil.java @@ -0,0 +1,67 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2008, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ----------------- + * TypeUtil.java + * ----------------- + * (C) Copyright 2006-2008, by John V. Sichi and Contributors. + * + * Original Author: John V. Sichi + * Contributor(s): - + * + * $Id$ + * + * Changes + * ------- + * 07-May-2006 : Initial version (JVS); + */ +package org.jgrapht.util; + +/** + * TypeUtil isolates type-unsafety so that code which uses it for legitimate + * reasons can stay warning-free. + * + * @author John V. Sichi + */ +public class TypeUtil +{ + //~ Methods ---------------------------------------------------------------- + + /** + * Casts an object to a type. + * + * @param o object to be cast + * @param typeDecl conveys the target type information; the actual value is + * unused and can be null since this is all just stupid compiler tricks + * + * @return the result of the cast + */ + @SuppressWarnings("unchecked") + public static T uncheckedCast(Object o, TypeUtil typeDecl) + { + return (T) o; + } +} + +// End TypeUtil.java diff --git a/wdl/org/jgrapht/util/VertexPair.java b/wdl/org/jgrapht/util/VertexPair.java new file mode 100644 index 0000000..5dc1c5a --- /dev/null +++ b/wdl/org/jgrapht/util/VertexPair.java @@ -0,0 +1,132 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * VertexPair.java + * ------------------------- + * (C) Copyright 2009-2009, by Soren Davidsen and Contributors + * + * Original Author: Soren Davidsen + * + * $Id$ + * + * Changes + * ------- + * 03-Dec-2009 : Initial revision (SD); + * + */ +package org.jgrapht.util; + +/** + * Representation of a pair of vertices; to be replaced by Pair if Sun ever + * gets around to adding Pair to java.util. + * + * @author Soren + */ +public class VertexPair +{ + //~ Instance fields -------------------------------------------------------- + + private V n1; + private V n2; + + //~ Constructors ----------------------------------------------------------- + + public VertexPair(V n1, V n2) + { + this.n1 = n1; + this.n2 = n2; + } + + //~ Methods ---------------------------------------------------------------- + + public V getFirst() + { + return n1; + } + + public V getSecond() + { + return n2; + } + + /** + * Assess if this pair contains the vertex. + * + * @param v The vertex in question + * + * @return true if contains, false otherwise + */ + public boolean hasVertex(V v) + { + return v.equals(n1) || v.equals(n2); + } + + public V getOther(V one) + { + if (one.equals(n1)) { + return n2; + } else if (one.equals(n2)) { + return n1; + } else { + return null; + } + } + + @Override public String toString() + { + return n1 + "," + n2; + } + + @Override public boolean equals(Object o) + { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + + @SuppressWarnings("unchecked") + VertexPair that = (VertexPair) o; + + if ((n1 != null) ? (!n1.equals(that.n1)) : (that.n1 != null)) { + return false; + } + if ((n2 != null) ? (!n2.equals(that.n2)) : (that.n2 != null)) { + return false; + } + + return true; + } + + @Override public int hashCode() + { + int result = (n1 != null) ? n1.hashCode() : 0; + result = (31 * result) + ((n2 != null) ? n2.hashCode() : 0); + return result; + } +} + +// End VertexPair.java diff --git a/wdl/org/jgrapht/util/WeightCombiner.java b/wdl/org/jgrapht/util/WeightCombiner.java new file mode 100644 index 0000000..637dd18 --- /dev/null +++ b/wdl/org/jgrapht/util/WeightCombiner.java @@ -0,0 +1,116 @@ +/* ========================================== + * JGraphT : a free Java graph-theory library + * ========================================== + * + * Project Info: http://jgrapht.sourceforge.net/ + * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) + * + * (C) Copyright 2003-2009, by Barak Naveh and Contributors. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ +/* ------------------------- + * WeightCombiner.java + * ------------------------- + * (C) Copyright 2009-2009, by Ilya Razenshteyn + * + * Original Author: Ilya Razenshteyn and Contributors. + * + * $Id$ + * + * Changes + * ------- + * 02-Feb-2009 : Initial revision (IR); + * + */ +package org.jgrapht.util; + +/** + * Binary operator for edge weights. There are some prewritten operators. + */ +public interface WeightCombiner +{ + //~ Instance fields -------------------------------------------------------- + + /** + * Sum of weights. + */ + public WeightCombiner SUM = + new WeightCombiner() { + public double combine(double a, double b) + { + return a + b; + } + }; + + /** + * Minimum weight. + */ + public WeightCombiner MIN = + new WeightCombiner() { + public double combine(double a, double b) + { + return Math.min(a, b); + } + }; + + /** + * Maximum weight. + */ + public WeightCombiner MAX = + new WeightCombiner() { + public double combine(double a, double b) + { + return Math.max(a, b); + } + }; + + /** + * First weight. + */ + public WeightCombiner FIRST = + new WeightCombiner() { + public double combine(double a, double b) + { + return a; + } + }; + + /** + * Second weight. + */ + public WeightCombiner SECOND = + new WeightCombiner() { + public double combine(double a, double b) + { + return b; + } + }; + + //~ Methods ---------------------------------------------------------------- + + /** + * Combines two weights. + * + * @param a first weight + * @param b second weight + * + * @return result of the operator + */ + double combine(double a, double b); +} + +// End WeightCombiner.java diff --git a/wdl/org/jgrapht/util/package.html b/wdl/org/jgrapht/util/package.html new file mode 100644 index 0000000..15706d5 --- /dev/null +++ b/wdl/org/jgrapht/util/package.html @@ -0,0 +1,7 @@ + + + +Non-graph-specific data structures, algorithms, and utilities used by +JGraphT. + + From 922e43cd6035782c348a29dc3565fc0410c09f7d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 23 Aug 2012 16:14:33 -0400 Subject: [PATCH 047/140] adding graph definition --- wdl/CompositeTask.java | 5 +++++ wdl/CompositeTaskEdge.java | 1 + wdl/CompositeTaskGraph.java | 34 ++++++++++++++++++++++++++++++++++ wdl/CompositeTaskVertex.java | 3 +++ 4 files changed, 43 insertions(+) create mode 100644 wdl/CompositeTaskGraph.java create mode 100644 wdl/CompositeTaskVertex.java diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 7f52583..c55637b 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.HashMap; import java.util.Iterator; +import org.jgrapht.DirectedGraph; class CompositeTask implements CompositeTaskScope { @@ -234,6 +235,10 @@ public String getName() { return this.nodes; } + public DirectedGraph getGraph() { + return null; + } + public CompositeTaskStep getStep(String name) { return null; } diff --git a/wdl/CompositeTaskEdge.java b/wdl/CompositeTaskEdge.java index ec34f07..ee248d0 100644 --- a/wdl/CompositeTaskEdge.java +++ b/wdl/CompositeTaskEdge.java @@ -1,2 +1,3 @@ class CompositeTaskEdge { + } diff --git a/wdl/CompositeTaskGraph.java b/wdl/CompositeTaskGraph.java new file mode 100644 index 0000000..81e2026 --- /dev/null +++ b/wdl/CompositeTaskGraph.java @@ -0,0 +1,34 @@ +import java.util.Set; +import java.util.Collection; +import org.jgrapht.DirectedGraph; +import org.jgrapht.EdgeFactory; + +class CompositeTaskGraph implements DirectedGraph +{ + public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} + public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} + public EdgeFactory getEdgeFactory() {return null;} + public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} + public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) {return false;} + public boolean addVertex(CompositeTaskVertex v) {return false;} + public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return false;} + public boolean containsEdge(CompositeTaskEdge e) {return false;} + public boolean containsVertex(CompositeTaskVertex v) {return false;} + public Set edgeSet() {return null;} + public Set edgesOf(CompositeTaskVertex vertex) {return null;} + public boolean removeAllEdges(Collection edges) {return false;} + public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} + public boolean removeAllVertices(Collection vertices) {return false;} + public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} + public boolean removeEdge(CompositeTaskEdge e) {return false;} + public boolean removeVertex(CompositeTaskVertex v) {return false;} + public Set vertexSet() {return null;} + public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) {return null;} + public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) {return null;} + public double getEdgeWeight(CompositeTaskEdge e) {return 1.0;} + + public int inDegreeOf(CompositeTaskVertex vertex) {return 0;} + public Set incomingEdgesOf(CompositeTaskVertex vertex) {return null;} + public int outDegreeOf(CompositeTaskVertex vertex) {return 0;} + public Set outgoingEdgesOf(CompositeTaskVertex vertex) {return null;} +} diff --git a/wdl/CompositeTaskVertex.java b/wdl/CompositeTaskVertex.java new file mode 100644 index 0000000..a7f9981 --- /dev/null +++ b/wdl/CompositeTaskVertex.java @@ -0,0 +1,3 @@ +class CompositeTaskVertex { + +} From dec663839ba1ba828b3269e45bb8862ebb6bbffe Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 24 Aug 2012 10:31:54 -0400 Subject: [PATCH 048/140] Adding some code to allow for the conversion of CompositeTask -> CompositeTaskGraph --- wdl/CompositeTask.java | 4 ++-- wdl/CompositeTaskEdgeFactory.java | 8 ++++++++ wdl/CompositeTaskScope.java | 2 +- wdl/CompositeTaskStep.java | 2 +- wdl/CompositeTaskVariable.java | 2 +- wdl/CompositeTaskVertex.java | 4 +--- 6 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 wdl/CompositeTaskEdgeFactory.java diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index c55637b..dbfd8f9 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -235,8 +235,8 @@ public String getName() { return this.nodes; } - public DirectedGraph getGraph() { - return null; + public CompositeTaskGraph getGraph() { + return new CompositeTaskGraph(); } public CompositeTaskStep getStep(String name) { diff --git a/wdl/CompositeTaskEdgeFactory.java b/wdl/CompositeTaskEdgeFactory.java new file mode 100644 index 0000000..320cba3 --- /dev/null +++ b/wdl/CompositeTaskEdgeFactory.java @@ -0,0 +1,8 @@ +import org.jgrapht.EdgeFactory; + +class CompositeTaskEdgeFactory implements EdgeFactory +{ + public CompositeTaskEdge createEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return null; + } +} diff --git a/wdl/CompositeTaskScope.java b/wdl/CompositeTaskScope.java index 4651dcc..3e6dadf 100644 --- a/wdl/CompositeTaskScope.java +++ b/wdl/CompositeTaskScope.java @@ -1,5 +1,5 @@ import java.util.Set; -interface CompositeTaskScope extends CompositeTaskNode { +interface CompositeTaskScope extends CompositeTaskNode, CompositeTaskVertex { public Set getNodes(); } diff --git a/wdl/CompositeTaskStep.java b/wdl/CompositeTaskStep.java index 3b4eb19..60bd0a9 100644 --- a/wdl/CompositeTaskStep.java +++ b/wdl/CompositeTaskStep.java @@ -1,6 +1,6 @@ import java.util.Set; -class CompositeTaskStep implements CompositeTaskNode { +class CompositeTaskStep implements CompositeTaskNode, CompositeTaskVertex { private CompositeTaskSubTask task; private String name; private Set inputs; diff --git a/wdl/CompositeTaskVariable.java b/wdl/CompositeTaskVariable.java index 2acfa08..8f3cfda 100644 --- a/wdl/CompositeTaskVariable.java +++ b/wdl/CompositeTaskVariable.java @@ -1,6 +1,6 @@ import java.util.Set; -class CompositeTaskVariable { +class CompositeTaskVariable implements CompositeTaskVertex { private String name; private String member; diff --git a/wdl/CompositeTaskVertex.java b/wdl/CompositeTaskVertex.java index a7f9981..4d07333 100644 --- a/wdl/CompositeTaskVertex.java +++ b/wdl/CompositeTaskVertex.java @@ -1,3 +1 @@ -class CompositeTaskVertex { - -} +interface CompositeTaskVertex {} From 07d12ecad2b66fd5cc8089356b618abac6741c1b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 24 Aug 2012 15:56:44 -0400 Subject: [PATCH 049/140] work in progress --- wdl/CompositeTask.java | 6 +++++- wdl/CompositeTaskForLoop.java | 10 +++++----- wdl/CompositeTaskGraph.java | 9 +++++++++ wdl/CompositeTaskVariable.java | 9 +++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index dbfd8f9..58b65ae 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -78,6 +78,10 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { return composite_task; } + private CompositeTaskVariable make_variable(String name, String member) { + + } + private CompositeTaskVariable ast_to_variable(Ast ast) { Terminal name = (Terminal) ast.getAttribute("name"); Terminal member = (Terminal) ast.getAttribute("member"); @@ -161,7 +165,7 @@ private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); - return new CompositeTaskForLoop(collection, item, nodes); + return new CompositeTaskForLoop(new CompositeTaskVariable(collection), new CompositeTaskVariable(item), nodes); } private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { diff --git a/wdl/CompositeTaskForLoop.java b/wdl/CompositeTaskForLoop.java index a87e66a..95cf2ea 100644 --- a/wdl/CompositeTaskForLoop.java +++ b/wdl/CompositeTaskForLoop.java @@ -1,11 +1,11 @@ import java.util.Set; class CompositeTaskForLoop implements CompositeTaskScope { - private String collection; - private String var; + private CompositeTaskVariable collection; + private CompositeTaskVariable var; private Set nodes; - public CompositeTaskForLoop(String collection, String var, Set nodes) { + public CompositeTaskForLoop(CompositeTaskVariable collection, CompositeTaskVariable var, Set nodes) { this.collection = collection; this.var = var; this.nodes = nodes; @@ -15,11 +15,11 @@ public Ast getAst() { return null; } - public String getCollectionName() { + public CompositeTaskVariable getCollectionName() { return this.collection; } - public String getVarName() { + public CompositeTaskVariable getVarName() { return this.var; } diff --git a/wdl/CompositeTaskGraph.java b/wdl/CompositeTaskGraph.java index 81e2026..7857e42 100644 --- a/wdl/CompositeTaskGraph.java +++ b/wdl/CompositeTaskGraph.java @@ -5,6 +5,15 @@ class CompositeTaskGraph implements DirectedGraph { + private Map for_loop_output; + public CompositeTaskGraph(CompositeTask composite_task) { + for_loop_output = new HashMap(); + } + + private generate_for_loop_output() { + + } + public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} public EdgeFactory getEdgeFactory() {return null;} diff --git a/wdl/CompositeTaskVariable.java b/wdl/CompositeTaskVariable.java index 8f3cfda..e16c1bd 100644 --- a/wdl/CompositeTaskVariable.java +++ b/wdl/CompositeTaskVariable.java @@ -33,6 +33,15 @@ public int hashCode() { } public boolean equals(CompositeTaskVariable other) { + if ( other.getName().equals(this.name) ) { + if ( other.getMember() == null && this.member == null ) { + return true; + } + + if ( other.getMember() != null && other.getMember().equals(this.member) ) { + return true; + } + } return false; } From da7cddd0ce87038df12d5449d9f857646d12ec59 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 27 Aug 2012 15:42:02 -0400 Subject: [PATCH 050/140] Adding CompositeTask -> CompositeTaskGraph conversion code --- wdl/CompositeTask.java | 73 ++++++++++----- wdl/CompositeTaskEdge.java | 26 ++++++ wdl/CompositeTaskEdgeFactory.java | 2 +- wdl/CompositeTaskForLoop.java | 30 ++++++- wdl/CompositeTaskGraph.java | 182 +++++++++++++++++++++++++++++++++++--- wdl/CompositeTaskNode.java | 2 + wdl/CompositeTaskScope.java | 1 + wdl/CompositeTaskStep.java | 18 ++++ wdl/WdlMain.java | 16 +++- wdl/examples/7.wdl | 18 ++++ 10 files changed, 330 insertions(+), 38 deletions(-) create mode 100644 wdl/examples/7.wdl diff --git a/wdl/CompositeTask.java b/wdl/CompositeTask.java index 58b65ae..a9d26f7 100644 --- a/wdl/CompositeTask.java +++ b/wdl/CompositeTask.java @@ -15,12 +15,15 @@ private WdlSyntaxErrorFormatter error_formatter; private Set nodes; private String name; + private CompositeTaskScope parent; private class CompositeTaskAstVerifier { private WdlSyntaxErrorFormatter syntaxErrorFormatter; + private Map variables; CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; + this.variables = new HashMap(); } public Ast verify(AstNode wdl_ast) throws SyntaxError { @@ -56,36 +59,34 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { CompositeTask.this.nodes.add(verify(node)); } - /* Graph definition: - * - * Verticies: - * scope, step, variable - * - * Edges: - * scope -> step : Step is dependent on scope completing - * scope (for) -> variable : Variable is the loop variable (not collection). - * Each for loop contains exactly one of these edges - * variable -> scope (for) : Variable is the loop collection - * variable -> step : Step needs variable as an input - * step -> variable : Variable is an output of step - * variable -> variable : Doesn't exist. - * scope -> scope : Doesn't exist. - * step -> scope : Doesn't exist. - * step -> step : Doesn't exist. - * - */ + set_parents(CompositeTask.this); return composite_task; } - private CompositeTaskVariable make_variable(String name, String member) { + private void set_parents(CompositeTaskScope scope) { + + for ( CompositeTaskNode node : scope.getNodes() ) { + node.setParent(scope); + if ( node instanceof CompositeTaskScope ) { + set_parents((CompositeTaskScope) node); + } + } } + private CompositeTaskVariable make_variable(String name, String member) { + String key = name + ((member == null) ? "" : member); + if ( !this.variables.containsKey(key) ) { + this.variables.put(key, new CompositeTaskVariable(name, member)); + } + return this.variables.get(key); + } + private CompositeTaskVariable ast_to_variable(Ast ast) { Terminal name = (Terminal) ast.getAttribute("name"); Terminal member = (Terminal) ast.getAttribute("member"); - return new CompositeTaskVariable(name.getSourceString(), (member == null) ? null : member.getSourceString()); + return make_variable(name.getSourceString(), (member == null) ? null : member.getSourceString()); } private CompositeTaskNode verify(Ast ast) throws SyntaxError { @@ -165,7 +166,7 @@ private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); - return new CompositeTaskForLoop(new CompositeTaskVariable(collection), new CompositeTaskVariable(item), nodes); + return new CompositeTaskForLoop(make_variable(collection, null), make_variable(item, null), nodes); } private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { @@ -202,9 +203,10 @@ private Terminal getTaskVersion(Ast task) { /** Constructors **/ - CompositeTask(String name, Set nodes) { + private CompositeTask(String name, Set nodes) { this.name = name; this.nodes = nodes; + this.parent = null; } CompositeTask(SourceCode source_code) throws SyntaxError { @@ -215,6 +217,7 @@ private Terminal getTaskVersion(Ast task) { AstList ast_list = (AstList) node.toAst(); CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); this.ast = verifier.verify(ast_list); + this.parent = null; } CompositeTask(File source_code) throws SyntaxError, IOException { @@ -240,7 +243,7 @@ public String getName() { } public CompositeTaskGraph getGraph() { - return new CompositeTaskGraph(); + return new CompositeTaskGraph(this); } public CompositeTaskStep getStep(String name) { @@ -266,6 +269,30 @@ public void setName(String name) { public void addNode(CompositeTaskNode node) { } + public void setParent(CompositeTaskScope parent) { + this.parent = parent; + } + + public CompositeTaskScope getParent() { + return this.parent; + } + + public boolean contains(CompositeTaskNode node) { + for ( CompositeTaskNode sub_node : this.nodes ) { + if ( node.equals(sub_node) ) { + return true; + } + + if ( sub_node instanceof CompositeTaskScope ) { + CompositeTaskScope scope = (CompositeTaskScope) sub_node; + if ( scope.contains(node) ) { + return true; + } + } + } + return false; + } + public String toString() { return "[CompositeTask name="+this.name+"]"; } diff --git a/wdl/CompositeTaskEdge.java b/wdl/CompositeTaskEdge.java index ee248d0..31829ec 100644 --- a/wdl/CompositeTaskEdge.java +++ b/wdl/CompositeTaskEdge.java @@ -1,3 +1,29 @@ class CompositeTaskEdge { + private CompositeTaskVertex start; + private CompositeTaskVertex end; + CompositeTaskEdge(CompositeTaskVertex start, CompositeTaskVertex end) { + this.start = start; + this.end = end; + } + + public CompositeTaskVertex getStart() { + return this.start; + } + + public CompositeTaskVertex getEnd() { + return this.end; + } + + public void setStart(CompositeTaskVertex start) { + this.start = start; + } + + public void setEnd(CompositeTaskVertex end) { + this.end = end; + } + + public String toString() { + return "[Edge\n from: "+this.start+"\n to: "+this.end+"\n]"; + } } diff --git a/wdl/CompositeTaskEdgeFactory.java b/wdl/CompositeTaskEdgeFactory.java index 320cba3..06379fe 100644 --- a/wdl/CompositeTaskEdgeFactory.java +++ b/wdl/CompositeTaskEdgeFactory.java @@ -3,6 +3,6 @@ class CompositeTaskEdgeFactory implements EdgeFactory { public CompositeTaskEdge createEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - return null; + return new CompositeTaskEdge(sourceVertex, targetVertex); } } diff --git a/wdl/CompositeTaskForLoop.java b/wdl/CompositeTaskForLoop.java index 95cf2ea..f3c5a33 100644 --- a/wdl/CompositeTaskForLoop.java +++ b/wdl/CompositeTaskForLoop.java @@ -4,22 +4,24 @@ private CompositeTaskVariable collection; private CompositeTaskVariable var; private Set nodes; + private CompositeTaskScope parent; public CompositeTaskForLoop(CompositeTaskVariable collection, CompositeTaskVariable var, Set nodes) { this.collection = collection; this.var = var; this.nodes = nodes; + this.parent = null; } public Ast getAst() { return null; } - public CompositeTaskVariable getCollectionName() { + public CompositeTaskVariable getCollection() { return this.collection; } - public CompositeTaskVariable getVarName() { + public CompositeTaskVariable getVariable() { return this.var; } @@ -27,6 +29,30 @@ public CompositeTaskVariable getVarName() { return this.nodes; } + public void setParent(CompositeTaskScope parent) { + this.parent = parent; + } + + public CompositeTaskScope getParent() { + return this.parent; + } + + public boolean contains(CompositeTaskNode node) { + for ( CompositeTaskNode sub_node : this.nodes ) { + if ( node.equals(sub_node) ) { + return true; + } + + if ( sub_node instanceof CompositeTaskScope ) { + CompositeTaskScope scope = (CompositeTaskScope) sub_node; + if ( scope.contains(node) ) { + return true; + } + } + } + return false; + } + public String toString() { return "[CompositeTaskForScope: collection=" + this.collection + ", var=" + this.var + ", # nodes=" + this.nodes.size()+ "]"; } diff --git a/wdl/CompositeTaskGraph.java b/wdl/CompositeTaskGraph.java index 7857e42..72df21f 100644 --- a/wdl/CompositeTaskGraph.java +++ b/wdl/CompositeTaskGraph.java @@ -1,29 +1,185 @@ import java.util.Set; import java.util.Collection; +import java.util.Map; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Comparator; +import java.util.Collections; import org.jgrapht.DirectedGraph; import org.jgrapht.EdgeFactory; class CompositeTaskGraph implements DirectedGraph { - private Map for_loop_output; + private Map> scope_output_map; + private Set verticies; + private Set edges; + private CompositeTaskEdgeFactory edge_factory; + public CompositeTaskGraph(CompositeTask composite_task) { - for_loop_output = new HashMap(); + this.scope_output_map = new HashMap>(); + this.edge_factory = new CompositeTaskEdgeFactory(); + this.verticies = new HashSet(); + this.edges = new HashSet(); + + generate_scope_output(composite_task); + generate_graph(composite_task); + } + + private void generate_graph(CompositeTaskScope scope) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + addVertex(step); + for ( CompositeTaskStepInput input : step.getInputs() ) { + CompositeTaskVariable var = input.getVariable(); + addVertex(var); + addEdge(var, step); + + if ( this.scope_output_map.containsKey(var) ) { + CompositeTaskScope closest = closest_scope(step, this.scope_output_map.get(var)); + addVertex(closest); + addEdge(closest, step); + } + } + + for ( CompositeTaskStepOutput output : step.getOutputs() ) { + CompositeTaskVariable var = output.getVariable(); + addVertex(var); + addEdge(step, var); + } + } + + if ( node instanceof CompositeTaskForLoop ) { + CompositeTaskForLoop loop = (CompositeTaskForLoop) node; + addVertex(loop); + addVertex(loop.getCollection()); + addVertex(loop.getVariable()); + addEdge(loop.getCollection(), loop); + addEdge(loop, loop.getVariable()); + generate_graph(loop); + } + } + } + + private class ScopeDepthComparator implements Comparator { + public int compare(CompositeTaskScope s1, CompositeTaskScope s2) { + int s1_depth, s2_depth; + CompositeTaskScope tmp; + + for (tmp=s1.getParent(), s1_depth=0; tmp != null; tmp = tmp.getParent(), s1_depth++); + for (tmp=s2.getParent(), s2_depth=0; tmp != null; tmp = tmp.getParent(), s2_depth++); + + if ( s1_depth < s2_depth ) return -1; + else if ( s1_depth > s2_depth ) return 1; + else return 0; + } + } + + private CompositeTaskScope closest_scope(CompositeTaskNode node, Set scopes) { + Set matches = new HashSet(); + for ( CompositeTaskScope scope : scopes ) { + if ( node.getParent().contains(scope) ) { + matches.add(scope); + } + } + + if (matches.size() > 0) { + return Collections.min(matches, new ScopeDepthComparator()); + } + return closest_scope(node.getParent(), scopes); + } + + private void generate_scope_output(CompositeTaskScope scope) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskScope ) { + CompositeTaskScope sub_scope = (CompositeTaskScope) node; + Set scope_outputs = get_outputs(sub_scope); + for ( CompositeTaskVariable variable : scope_outputs ) { + if ( !scope_output_map.containsKey(variable) ) { + scope_output_map.put(variable, new HashSet()); + } + scope_output_map.get(variable).add(sub_scope); + generate_scope_output(sub_scope); + } + } + } + } + + private Set get_outputs(CompositeTaskScope scope) { + Set outputs = new HashSet(); + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + for ( CompositeTaskStepOutput step_output : step.getOutputs() ) { + outputs.add( step_output.getVariable() ); + } + } + + if ( node instanceof CompositeTaskScope ) { + outputs.addAll( get_outputs((CompositeTaskScope) node) ); + } + } + return outputs; } - private generate_for_loop_output() { + public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return this.edges; + } + + public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getStart().equals(sourceVertex) && edge.getEnd().equals(targetVertex) ) { + return edge; + } + } + return null; + } + + public EdgeFactory getEdgeFactory() { + return this.edge_factory; + } + public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + if ( getEdge(sourceVertex, targetVertex) != null ) { + return null; + } + + if ( !containsVertex(sourceVertex) || !containsVertex(targetVertex) ) { + return null; + } + + CompositeTaskEdge edge = this.edge_factory.createEdge(sourceVertex, targetVertex); + this.edges.add(edge); + return edge; } - public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} - public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} - public EdgeFactory getEdgeFactory() {return null;} - public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) {return false;} - public boolean addVertex(CompositeTaskVertex v) {return false;} + + public boolean addVertex(CompositeTaskVertex v) { + if ( containsVertex(v) ) { + return false; + } + + this.verticies.add(v); + return true; + } + public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return false;} public boolean containsEdge(CompositeTaskEdge e) {return false;} - public boolean containsVertex(CompositeTaskVertex v) {return false;} - public Set edgeSet() {return null;} + + public boolean containsVertex(CompositeTaskVertex v) { + for ( CompositeTaskVertex vertex : this.verticies ) { + if ( v.equals(vertex) ) { + return true; + } + } + return false; + } + + public Set edgeSet() { + return this.edges; + } + public Set edgesOf(CompositeTaskVertex vertex) {return null;} public boolean removeAllEdges(Collection edges) {return false;} public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} @@ -31,7 +187,11 @@ private generate_for_loop_output() { public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} public boolean removeEdge(CompositeTaskEdge e) {return false;} public boolean removeVertex(CompositeTaskVertex v) {return false;} - public Set vertexSet() {return null;} + + public Set vertexSet() { + return this.verticies; + } + public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) {return null;} public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) {return null;} public double getEdgeWeight(CompositeTaskEdge e) {return 1.0;} diff --git a/wdl/CompositeTaskNode.java b/wdl/CompositeTaskNode.java index 5e301f3..1d22c20 100644 --- a/wdl/CompositeTaskNode.java +++ b/wdl/CompositeTaskNode.java @@ -1,3 +1,5 @@ interface CompositeTaskNode { public Ast getAst(); + public void setParent(CompositeTaskScope parent); + public CompositeTaskScope getParent(); } diff --git a/wdl/CompositeTaskScope.java b/wdl/CompositeTaskScope.java index 3e6dadf..6c9ebe7 100644 --- a/wdl/CompositeTaskScope.java +++ b/wdl/CompositeTaskScope.java @@ -2,4 +2,5 @@ interface CompositeTaskScope extends CompositeTaskNode, CompositeTaskVertex { public Set getNodes(); + public boolean contains(CompositeTaskNode node); } diff --git a/wdl/CompositeTaskStep.java b/wdl/CompositeTaskStep.java index 60bd0a9..ad8b280 100644 --- a/wdl/CompositeTaskStep.java +++ b/wdl/CompositeTaskStep.java @@ -5,12 +5,14 @@ private String name; private Set inputs; private Set outputs; + private CompositeTaskScope parent; public CompositeTaskStep(String name, CompositeTaskSubTask task, Set inputs, Set outputs) { this.task = task; this.name = name; this.inputs = inputs; this.outputs = outputs; + this.parent = null; } public Ast getAst() { @@ -25,6 +27,22 @@ public CompositeTaskSubTask getTask() { return this.task; } + public Set getOutputs() { + return this.outputs; + } + + public Set getInputs() { + return this.inputs; + } + + public void setParent(CompositeTaskScope parent) { + this.parent = parent; + } + + public CompositeTaskScope getParent() { + return this.parent; + } + public int hashCode() { return 0; } diff --git a/wdl/WdlMain.java b/wdl/WdlMain.java index 9d78825..8b8e318 100644 --- a/wdl/WdlMain.java +++ b/wdl/WdlMain.java @@ -29,7 +29,21 @@ public static void main(String[] args) { } else if ( args[1].equals("entities") ) { print_tree(ctask); } else if ( args[1].equals("graph") ) { - System.out.println(ctask); + CompositeTaskGraph graph = ctask.getGraph(); + + System.out.println("VERTICIES"); + System.out.println("---------"); + for ( CompositeTaskVertex v : graph.vertexSet() ) { + System.out.println(v); + } + System.out.println(""); + + System.out.println("EDGES"); + System.out.println("-----"); + for ( CompositeTaskEdge v : graph.edgeSet() ) { + System.out.println(v); + } + } else { usage(); } diff --git a/wdl/examples/7.wdl b/wdl/examples/7.wdl new file mode 100644 index 0000000..9cfe189 --- /dev/null +++ b/wdl/examples/7.wdl @@ -0,0 +1,18 @@ +composite_task test { + step s0[version=0] { + output: File("abc") as foo; + } + + for (I in L) { + for (J in M) { + step s1[version=0] { + input: p0=I, p1=J, p2=foo; + output: File("def") as bar; + } + } + } + + step s2[version=0] { + input: p0=bar; + } +} From 707f5b455028cdebdb591e26d9bf5a7fe9ca4686 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 27 Aug 2012 15:45:33 -0400 Subject: [PATCH 051/140] new readme --- wdl/README.md | 258 +++++++++++++++++++++++----------------------------------- 1 file changed, 102 insertions(+), 156 deletions(-) diff --git a/wdl/README.md b/wdl/README.md index dfb8979..2c2d2d9 100644 --- a/wdl/README.md +++ b/wdl/README.md @@ -23,36 +23,30 @@ $ javac *.java The data file we'll use is: ``` -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; +composite_task test { + step s0[version=0] { + output: File("abc") as foo; } - for ( item in foo ) { - step btask[version=0] { - input: p0=x, p1=s; - output: File("bar.txt") as y; - } - - step ctask[version=0] { - input: p0=x, p1=y; - output: File("quux.txt") as z; + for (I in L) { + for (J in M) { + step s1[version=0] { + input: p0=I, p1=J, p2=foo; + output: File("def") as bar; + } } } - step dtask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as r; + step s2[version=0] { + input: p0=bar; } - } ``` Get the abstract syntax tree: ``` -$ java WdlMain examples/0.wdl ast +$ java WdlMain examples/7.wdl ast (CompositeTask: body=[ (Step: @@ -82,91 +76,61 @@ $ java WdlMain examples/0.wdl ast ), (ForLoop: body=[ - (Step: + (ForLoop: body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] ) - ] - ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None - ), - (Step: - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string - ) - ] + ], + name=identifier + ), + name=None ) ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + item=identifier, + collection=identifier ) ], item=identifier, @@ -182,31 +146,6 @@ $ java WdlMain examples/0.wdl ast member=None, name=identifier ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string ) ] ) @@ -230,58 +169,65 @@ $ java WdlMain examples/0.wdl ast Get a view of the graph ``` -$ java WdlMain examples/0.wdl graph -[Step: name=dtask] -[Step: name=atask] -[CompositeTaskForScope: collection=foo, var=item, # nodes=2] +$ java WdlMain examples/7.wdl graph +VERTICIES +--------- +[Step: name=s1] +[Variable: name=J] +[Variable: name=M] +[Variable: name=I] +[Variable: name=L] +[Variable: name=foo] +[Step: name=s0] +[Variable: name=bar] +[Step: name=s2] +[CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Variable: name=I] +] [Edge - from=[Output node=[Step: name=atask], path="foo.txt"], - to=[Input node=[Step: name=dtask], param=p0], - var=x + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Step: name=s2] ] [Edge - from=[Output node=[Step: name=atask], path="foo.txt"], - to=[Input node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], param=null], - var=x + from: [Variable: name=J] + to: [Step: name=s1] ] [Edge - from=[Output node=[Step: name=atask], path="foo.txt"], - to=[Input node=[Step: name=btask], param=p0], - var=x + from: [Variable: name=L] + to: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] ] [Edge - from=[Output node=[Step: name=atask], path="foo.txt"], - to=[Input node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], param=null], - var=x + from: [Variable: name=foo] + to: [Step: name=s1] ] [Edge - from=[Output node=[Step: name=atask], path="foo.txt"], - to=[Input node=[Step: name=ctask], param=p0], - var=x + from: [Variable: name=I] + to: [Step: name=s1] ] [Edge - from=[Output node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], path="bar.txt"], - to=[Input node=[Step: name=dtask], param=p1], - var=y + from: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + to: [Variable: name=J] ] [Edge - from=[Output node=[Step: name=btask], path="bar.txt"], - to=[Input node=[Step: name=dtask], param=p1], - var=y + from: [Step: name=s0] + to: [Variable: name=foo] ] [Edge - from=[Output node=[Step: name=btask], path="bar.txt"], - to=[Input node=[Step: name=ctask], param=p1], - var=y + from: [Step: name=s1] + to: [Variable: name=bar] ] [Edge - from=[Output node=[CompositeTaskForScope: collection=foo, var=item, # nodes=2], path="quux.txt"], - to=[Input node=[Step: name=dtask], param=p2], - var=z + from: [Variable: name=bar] + to: [Step: name=s2] ] [Edge - from=[Output node=[Step: name=ctask], path="quux.txt"], - to=[Input node=[Step: name=dtask], param=p2], - var=z + from: [Variable: name=M] + to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] ] ``` From e231475a51d1b1e30c98aa5529cead0bf053644d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 27 Aug 2012 15:56:03 -0400 Subject: [PATCH 052/140] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e92f57 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tags From ecb6585c0e91c24ee8e244047220397b85ce9f5a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 27 Aug 2012 16:03:23 -0400 Subject: [PATCH 053/140] mis-spelled file --- wdl/{CompositeTasStepInput.java => CompositeTaskStepInput.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wdl/{CompositeTasStepInput.java => CompositeTaskStepInput.java} (100%) diff --git a/wdl/CompositeTasStepInput.java b/wdl/CompositeTaskStepInput.java similarity index 100% rename from wdl/CompositeTasStepInput.java rename to wdl/CompositeTaskStepInput.java From 03c28f478624c2c595e703d76fe58501e1a9da9d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 11:25:55 -0400 Subject: [PATCH 054/140] removing unnecessary function --- wdl/CompositeTaskVariable.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/wdl/CompositeTaskVariable.java b/wdl/CompositeTaskVariable.java index e16c1bd..cf5edad 100644 --- a/wdl/CompositeTaskVariable.java +++ b/wdl/CompositeTaskVariable.java @@ -13,9 +13,6 @@ public CompositeTaskVariable(String name) { this.name = name; } - public CompositeTaskVariable(Ast ast) { - } - public Ast getAst() { return null; } From d83b9d5eecb1bb93e9b24369092d51d46fc59304 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 11:27:32 -0400 Subject: [PATCH 055/140] Removing DOT parser --- dot/.1.dot.swo | Bin 16384 -> 0 bytes dot/.1.dot.swp | Bin 16384 -> 0 bytes dot/.dot.zgr.swp | Bin 12288 -> 0 bytes dot/0.dot | 1 - dot/1.dot | 2143 ---------------------------------- dot/2.dot | 27 - dot/3.dot | 104 -- dot/4.dot | 20 - dot/5.dot | 2212 ------------------------------------ dot/6.dot | 2140 ---------------------------------- dot/Ast.java | 46 - dot/AstList.java | 20 - dot/AstNode.java | 5 - dot/AstTransform.java | 1 - dot/AstTransformNodeCreator.java | 24 - dot/AstTransformSubstitution.java | 12 - dot/DotParser.java | 959 ---------------- dot/ExpressionParser.java | 3 - dot/Lexer.java | 416 ------- dot/NonTerminal.java | 17 - dot/ParseTree.java | 159 --- dot/ParseTreeNode.java | 6 - dot/Parser.java | 4 - dot/ParserMain.java | 50 - dot/SyntaxError.java | 5 - dot/TODO | 40 - dot/Terminal.java | 51 - dot/TerminalMap.java | 6 - dot/TokenStream.java | 44 - dot/Utility.java | 81 -- dot/dot.zgr | 28 - dot/org/json/CDL.java | 279 ----- dot/org/json/Cookie.java | 169 --- dot/org/json/CookieList.java | 90 -- dot/org/json/HTTP.java | 163 --- dot/org/json/HTTPTokener.java | 77 -- dot/org/json/JSONArray.class | Bin 9162 -> 0 bytes dot/org/json/JSONArray.java | 906 --------------- dot/org/json/JSONException.class | Bin 587 -> 0 bytes dot/org/json/JSONException.java | 28 - dot/org/json/JSONML.java | 467 -------- dot/org/json/JSONObject$1.class | Bin 199 -> 0 bytes dot/org/json/JSONObject$Null.class | Bin 656 -> 0 bytes dot/org/json/JSONObject.class | Bin 17385 -> 0 bytes dot/org/json/JSONObject.java | 1593 -------------------------- dot/org/json/JSONString.class | Bin 156 -> 0 bytes dot/org/json/JSONString.java | 18 - dot/org/json/JSONStringer.java | 78 -- dot/org/json/JSONTokener.class | Bin 5033 -> 0 bytes dot/org/json/JSONTokener.java | 446 -------- dot/org/json/JSONWriter.java | 327 ------ dot/org/json/XML.java | 508 --------- dot/org/json/XMLTokener.java | 365 ------ 53 files changed, 14138 deletions(-) delete mode 100644 dot/.1.dot.swo delete mode 100644 dot/.1.dot.swp delete mode 100644 dot/.dot.zgr.swp delete mode 100644 dot/0.dot delete mode 100644 dot/1.dot delete mode 100644 dot/2.dot delete mode 100644 dot/3.dot delete mode 100644 dot/4.dot delete mode 100644 dot/5.dot delete mode 100644 dot/6.dot delete mode 100644 dot/Ast.java delete mode 100644 dot/AstList.java delete mode 100644 dot/AstNode.java delete mode 100644 dot/AstTransform.java delete mode 100644 dot/AstTransformNodeCreator.java delete mode 100644 dot/AstTransformSubstitution.java delete mode 100644 dot/DotParser.java delete mode 100644 dot/ExpressionParser.java delete mode 100644 dot/Lexer.java delete mode 100644 dot/NonTerminal.java delete mode 100644 dot/ParseTree.java delete mode 100644 dot/ParseTreeNode.java delete mode 100644 dot/Parser.java delete mode 100644 dot/ParserMain.java delete mode 100644 dot/SyntaxError.java delete mode 100644 dot/TODO delete mode 100644 dot/Terminal.java delete mode 100644 dot/TerminalMap.java delete mode 100644 dot/TokenStream.java delete mode 100644 dot/Utility.java delete mode 100644 dot/dot.zgr delete mode 100755 dot/org/json/CDL.java delete mode 100755 dot/org/json/Cookie.java delete mode 100755 dot/org/json/CookieList.java delete mode 100755 dot/org/json/HTTP.java delete mode 100755 dot/org/json/HTTPTokener.java delete mode 100644 dot/org/json/JSONArray.class delete mode 100644 dot/org/json/JSONArray.java delete mode 100644 dot/org/json/JSONException.class delete mode 100755 dot/org/json/JSONException.java delete mode 100755 dot/org/json/JSONML.java delete mode 100644 dot/org/json/JSONObject$1.class delete mode 100644 dot/org/json/JSONObject$Null.class delete mode 100644 dot/org/json/JSONObject.class delete mode 100755 dot/org/json/JSONObject.java delete mode 100644 dot/org/json/JSONString.class delete mode 100755 dot/org/json/JSONString.java delete mode 100755 dot/org/json/JSONStringer.java delete mode 100644 dot/org/json/JSONTokener.class delete mode 100644 dot/org/json/JSONTokener.java delete mode 100755 dot/org/json/JSONWriter.java delete mode 100755 dot/org/json/XML.java delete mode 100755 dot/org/json/XMLTokener.java diff --git a/dot/.1.dot.swo b/dot/.1.dot.swo deleted file mode 100644 index cfd1ad4c010379e05b4b9b95e4dca486aee557fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 Vj~tapR(a&8ysZ1>ymHzz{2QyhEDQhu diff --git a/dot/.1.dot.swp b/dot/.1.dot.swp deleted file mode 100644 index 7898869f4d430bf13777041bf354d4ce3a31ab5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHNZKxeb8D6!vCMGpREd@*2ZUrGGxjQqvvolRk)zYMDtu1J(5T(rS%-(zB%{hm2 zPtqoSRnZ~{1))Er^hfbWn;$A7Dn%4UqzH;ikzy64YMW|5{HR~i+SX_H?9T38uxGaV zqrx6|ayR>&cjkTGnR(xtxi<}Oc-yspvY&bQ?DD+N>>FM8ogKUPJbtO?ZRRs|%FGJp zc|X~zBG3DUiu_2`;L3D1Icl=`=E_ZaV?|HqD`Y?Zb!lSw&Jcki0xviMJ3U58SeRcL zT;jia_u&`Z(qK45V2HpFfgu7z1cnF<5f~ycL|}-(|6c^=)4=;E+r1SH+ z>cgw|vco@H@k#Z5(&3+}__%t1cZdI1hyQtpf4bBEuFApM&wo~YRM{Qs@c-!8pX%^u zJN%bA{NFqLnGXNAiod+-|Dr0O)z`egR{WI}|K1M&mx_N=#oy84|J>mp?C?)j{HU_O z@MVjKy8k~_d_8W5JNzFjz8>G(I{Y6h{y^3KcRT#=E56qMT!(+M;ty5!2hQ2*-xC#o zu;M?~;UBN~t1AA!4*yuke*4R}w*R{he_eLAMEgFI{d}wZtee(4xe@S zhdcb~4*#2qzqZoi+I{c42d^Mcj!K(e&y<%(o)$8HM z5P=~ALj;Bh3=tS2FhpR8zz~5U0x#kSDD9Pd`nMDZMg0E1KL3B=Rh~BkCct|D4m@(c z=bZ+Q0~Rv<13Zdz&S!yl0p|ff!nx}%;Cf&u@O_*EZvhSgPvemC4PXqs z5jcZ0@;yLt)_x6eKQw*&eHQizn&x)nz!649QvMB$T$oViCNfbvF0z(OHO$PG)~n;=Q8 zM=8NY&f|lU!*cRc}#I;gVx236l2GwE7v%C@G+<$8+rUn}Zc;r4jO*W51$!UhghnY_$ z!xqY6!L82TUd_N;imznSZ)zwheJ^;2fVlS}Y8 zIbmiSYC4+E);Ev&``$erua*t&Up?Vpv3SBOZ)J}^Ut8bw7j5GqpG}V8m07$wv3|;* z&CTX~W$^{QKEq$xPi80g`|nWe+MgVs`)aKHnHg&{Gul_1UUB}v6=&hE;e1@2{|{DY z;veF?ePjKe{954m00CoUB!`c5da00jr*bO{{^Zyrt4*_onE(Fft4&W=m z$ARmCi-9L_7w~o9Q@{w%|mAMkD9HsF209^fqQ1nvWF2T~vep2gk34}d#>HGl)> z0QcjL;4WYcTn=mpeu{g7yMZ}yC9n(lCGHD851azt3S0m@j5~ub1GfP01TF#|LtO3! ziuioBh|%zQ5k%m_xaAOGam%sq3Lj5pu3OxxOpni|8)mPsX0ypnYewnO7|U;QFT#rq zQdlI5?6};bJW!Svi|pfIQJmHmeU!H_4i-h_SoBer*yR>wt?A{J8mo&D(N|R;>EZ-Li`I>BDvI zHeQKhWO^xg9l<76qL`EY`Y3mNy_7qSc}sb@k6YdcFMKIyJ9pJ#*Ex6eDylPF61iFw zv#Inda@0{?UY8ckF<()eMVaGFEU%=>KB(ioDvzZL3&-eEtDHLOC~qtmeK_hUF9%Bt z;;5s%2rDd@bhWUvggA~lvC4^~^74*np~F#mXlHxqI3DFuzU(7()4|IF?!v;&D_+*J z!U8wOPPv53S_dyH;_~dnZ8hN1RYyG@+_4()GCwbLI4ZaM67HC(d08*ZJ{^P}QF&~Y$BxQlJLa+Dn8#Lm>^SDJRUSJkkF4_8QF&yQ VM~=!Pt2}a4Ue^6`UODX<{tc-yEHD57 diff --git a/dot/.dot.zgr.swp b/dot/.dot.zgr.swp deleted file mode 100644 index 0a04aae50b6b1794efe24ed0f1773b03e5d696f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI1OKTHR6vuB|`Dzur)WvlS%+#iB(uztkg@RHFJ_=$tQo>DUnv6~|NjIQt+uF*HAr7RPaV!jGJNE#HwB~l(zmD`f zQOJe}5P>5E`f6+T`UG2Cs8#j5OV&j`b?(6tGkQP-hyW2F0z`la5CI}U1c<=@OF%^> z_5#W~mX>%Sy_SZq=`CG|01+SpM1Tko0U|&IhyW2F0z`la5P^S?fN&XmbDXj22}mCP z|DXN-KRmVesVxX``ue_mFd2ZWlgb{icQij_$-{-a~;*OSG(8VC3)NRG#)GM;U`#gJE z*rQ|FiM3r8Bu&-y0^n{z3OBu0Af(Wf?Ih-ECrXA)2Z0i}F(T+M2a?|n0x_e^@Ghc3 zQ%I`9YkIl|ap^o9tONBY;Hc>K;1|uym>0CqdQ>bPhQ5-O;^Ym-GJw3f^)g4ci97H25IsBT#;6voU~>{; zuq#qxW>d3BINNx$pA2OBy{K!{)FZ0dCoynd65@a%InZI!%>(^PHtCk^2VQI~@rQW6TVNy=+*+6;7GwoM4W8_=J@ymc Cpg`CF diff --git a/dot/0.dot b/dot/0.dot deleted file mode 100644 index 3f2b189..0000000 --- a/dot/0.dot +++ /dev/null @@ -1 +0,0 @@ -digraph G {Hello->World} diff --git a/dot/1.dot b/dot/1.dot deleted file mode 100644 index fff85a1..0000000 --- a/dot/1.dot +++ /dev/null @@ -1,2143 +0,0 @@ -/* this graph is from the graphviz rtest/graph directory. Laid out and rendered as - sfdp -Gsize=67! -Goverlap=prism -Tpng root.gv > root.png -*/ -digraph G_component_0 { - graph [ranksep=3, root="189E"]; - 1 [label="02f5daf56e299b8a8ecea892", shape=hexagon, style=filled, color=green]; - "189E" [label=ca5af2, shape=box, style=filled, color=blue]; - "790E" [label=b4dfef6, shape=box, style=filled, color=grey]; - 2 [label="171192dc1f8e6ea551548a910c00", shape=hexagon, style=filled, color=green]; - "191E" [label="629e42", shape=box, style=filled, color=grey]; - 3 [label="6bce02baf91781a831e1b95", shape=hexagon, style=filled, color=green]; - "193E" [label="1c08373", shape=box, style=filled, color=grey]; - 4 [label="6236a67933a619a6a3d48", shape=hexagon, style=filled, color=green]; - "195E" [label=be8f4199f, shape=box, style=filled, color=grey]; - 5 [label="50962c93b4cb293f5beb59eb", shape=hexagon, style=filled, color=green]; - "197E" [label=be8f4199f, shape=box, style=filled, color=grey]; - 6 [label="05d4b1ed6a6135eec3abd3f2", shape=hexagon, style=filled, color=green]; - "199E" [shape=box, style=filled, color=grey]; - 7 [label="08769f73d31c1a99be2d9363f", shape=hexagon, style=filled, color=green]; - "201E" [label="629e42", shape=box, style=filled, color=grey]; - 8 [label=a6a196a504c3a7657d1fa41, shape=hexagon, style=filled, color=green]; - "203E" [label=cd856f, shape=box, style=filled, color=grey]; - 9 [label="837ebf4bde22e1f1535cb662", shape=hexagon, style=filled, color=green]; - "725E" [label=d0eb84, shape=box, style=filled, color=grey]; - "785E" [label=dd2ba36, shape=box, style=filled, color=grey]; - 10 [label="5f865c374cb3fe976dd376b8", shape=hexagon, style=filled, color=green]; - "205E" [label="23ad1", shape=box, style=filled, color=grey]; - 11 [label="8be752bc95d436a90493bec9", shape=hexagon, style=filled, color=green]; - "207E" [label=ee91c97828, shape=box, style=filled, color=grey]; - 12 [label="969a58db14386cb9d2f51ec", shape=hexagon, style=filled, color=green]; - "209E" [label="7c7c", shape=box, style=filled, color=grey]; - 13 [label=da24f74aad2ff519009d1f38c, shape=hexagon, style=filled, color=green]; - "211E" [label="460aed10cc9", shape=box, style=filled, color=grey]; - 14 [label="3124d3a6ed3381a6341c6", shape=hexagon, style=filled, color=green]; - "213E" [label=bbe0a8f93dc1, shape=box, style=filled, color=grey]; - 15 [label="71512ec7d43f958f2b6da", shape=hexagon, style=filled, color=green]; - "215E" [label="3f0a2b4eb62f", shape=box, style=filled, color=grey]; - 16 [label="3828a2c682419423cf", shape=hexagon, style=filled, color=green]; - "727E" [label=2, shape=box, style=filled, color=grey]; - "784E" [shape=box, style=filled, color=grey]; - 17 [label=aa868f65c34cdb64f1fad19a, shape=hexagon, style=filled, color=green]; - "217E" [label="3089106e3b", shape=box, style=filled, color=grey]; - "787E" [label="1aaaab063", shape=box, style=filled, color=grey]; - 18 [label=dca32af03698c988b22, shape=hexagon, style=filled, color=green]; - "219E" [label=eb8, shape=box, style=filled, color=grey]; - 19 [label=d8f4a9e463a1e89217f, shape=hexagon, style=filled, color=green]; - "221E" [label="4c6c8c", shape=box, style=filled, color=grey]; - 20 [label=c96782ef56711c5d6a3f69, shape=hexagon, style=filled, color=green]; - "223E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; - 21 [label="4f04c39708f", shape=hexagon, style=filled, color=green]; - "225E" [label=a49284e9, shape=box, style=filled, color=grey]; - 22 [label="97284d4c3a5d499853f0e", shape=hexagon, style=filled, color=green]; - "227E" [label="53069e384a2", shape=box, style=filled, color=grey]; - "792E" [label="79b69c612", shape=box, style=filled, color=grey]; - 23 [label=c4d32527b670afb370d643, shape=hexagon, style=filled, color=green]; - "231E" [label=e851f5ddd920, shape=box, style=filled, color=grey]; - 24 [label="5e9156098c064", shape=hexagon, style=filled, color=green]; - "233E" [shape=box, style=filled, color=grey]; - 25 [label="3d475ea3aeca51b60212dd", shape=hexagon, style=filled, color=green]; - "235E" [label="4280833ef80172", shape=box, style=filled, color=grey]; - 26 [label="966d271c22e75c7538", shape=hexagon, style=filled, color=green]; - "237E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 27 [label=b630e1af6ae1997f0e8ba750, shape=hexagon, style=filled, color=green]; - "239E" [label=bb828f1a326, shape=box, style=filled, color=grey]; - "783E" [label="499f6985db294c", shape=box, style=filled, color=grey]; - 28 [label=ebd8ffc2ac3a90efb8af9, shape=hexagon, style=filled, color=green]; - "241E" [label="1ebeec", shape=box, style=filled, color=grey]; - "791E" [label=c0b727, shape=box, style=filled, color=grey]; - 29 [label="69fdd1a1f4768c5efe7", shape=hexagon, style=filled, color=green]; - "243E" [label="35b8742610", shape=box, style=filled, color=grey]; - 30 [label=d93a80739fc1edb41a11b7294, shape=hexagon, style=filled, color=green]; - "245E" [label=e03b8bc0435a, shape=box, style=filled, color=grey]; - 31 [label=bf65cfddeb00ff847feae0c, shape=hexagon, style=filled, color=green]; - "247E" [label="8df", shape=box, style=filled, color=grey]; - 32 [label="916c686a1e82dba72524a", shape=hexagon, style=filled, color=green]; - "249E" [label=a849f9d352e, shape=box, style=filled, color=grey]; - 33 [label=f496bcf0889b301d77819c, shape=hexagon, style=filled, color=green]; - "251E" [label=f29dfb9, shape=box, style=filled, color=grey]; - 34 [label="76889f7d35e", shape=hexagon, style=filled, color=green]; - "253E" [label=e7ef998, shape=box, style=filled, color=grey]; - 35 [label="668d636002", shape=hexagon, style=filled, color=green]; - "255E" [label="4379b5ed", shape=box, style=filled, color=grey]; - 36 [label=e1e4c23db39d8bd633c3a, shape=hexagon, style=filled, color=green]; - "257E" [label="1ed5d7f63b8c6", shape=box, style=filled, color=grey]; - 37 [label="842bc5775657c1e0d67", shape=hexagon, style=filled, color=green]; - "259E" [label=a387210a27b, shape=box, style=filled, color=grey]; - 38 [label=e4e2f4e6d, shape=hexagon, style=filled, color=green]; - "261E" [label="1f4f0fdf", shape=box, style=filled, color=grey]; - 39 [label="04390dec6f1779353c07f5", shape=hexagon, style=filled, color=green]; - "263E" [label=bac77c3f414a, shape=box, style=filled, color=grey]; - 40 [label="69f2611acc42c36ed7cc", shape=hexagon, style=filled, color=green]; - "265E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 41 [label="1562abef0d8241", shape=hexagon, style=filled, color=green]; - "267E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; - 42 [label=e49aaa5cc4e44355d6a0, shape=hexagon, style=filled, color=green]; - "269E" [label=cc3f63d, shape=box, style=filled, color=grey]; - 43 [label=e8ebe1bf5f421c1223, shape=hexagon, style=filled, color=green]; - "271E" [label="96325ea", shape=box, style=filled, color=grey]; - 44 [label="2759e82e30d6d", shape=hexagon, style=filled, color=green]; - "273E" [label=ca5af2, shape=box, style=filled, color=grey]; - 45 [label="23c1ec53358d237c1", shape=hexagon, style=filled, color=green]; - "275E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 46 [label="5838586c293d455", shape=hexagon, style=filled, color=green]; - "277E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; - 47 [label=f841118350a27b7ea29a9c9d, shape=hexagon, style=filled, color=green]; - "279E" [label="69f4ecb77d", shape=box, style=filled, color=grey]; - 48 [label="658d208447d8ec5d6de8", shape=hexagon, style=filled, color=green]; - "281E" [label=f7b22b9640, shape=box, style=filled, color=grey]; - 49 [label="11180ae7706510211bc4", shape=hexagon, style=filled, color=green]; - "283E" [label="052bb6e3", shape=box, style=filled, color=grey]; - 50 [label="5807acd8d58e006f43", shape=hexagon, style=filled, color=green]; - "285E" [shape=box, style=filled, color=grey]; - 51 [label=fe4e848cb5291ee59a2, shape=hexagon, style=filled, color=green]; - "287E" [label=e3aefac763, shape=box, style=filled, color=grey]; - 52 [label=c4f31ea3844e12da27ad47c6, shape=hexagon, style=filled, color=green]; - "289E" [label=fb16636aae, shape=box, style=filled, color=grey]; - 53 [label="00cbeb87c182ca0785f", shape=hexagon, style=filled, color=green]; - "291E" [label="3089106e3b", shape=box, style=filled, color=grey]; - 54 [label="11f088bfd8", shape=hexagon, style=filled, color=green]; - "293E" [label="6a80cbe", shape=box, style=filled, color=grey]; - 56 [label="3c2a62e0e5e9f7", shape=hexagon, style=filled, color=green]; - "295E" [label=ae32701, shape=box, style=filled, color=grey]; - 57 [label=dd84fe6a65cfac7bca03ebd, shape=hexagon, style=filled, color=green]; - "297E" [shape=box, style=filled, color=grey]; - 58 [label=b06bbfa920aa95dd, shape=hexagon, style=filled, color=green]; - "299E" [label=07, shape=box, style=filled, color=grey]; - 59 [label="6b5aaa4bdf44b2c898854", shape=hexagon, style=filled, color=green]; - "301E" [label="4c6c8c", shape=box, style=filled, color=grey]; - "789E" [label="3a0ff0", shape=box, style=filled, color=grey]; - 60 [label="855d26296eda4eb7", shape=hexagon, style=filled, color=green]; - "303E" [label="53069e384a2", shape=box, style=filled, color=grey]; - 61 [label=e82f47b8d4949ba4af69b38cbc19, shape=hexagon, style=filled, color=green]; - "305E" [label=b62cd1d0a0, shape=box, style=filled, color=grey]; - 62 [label="86569bffb49adf6b3d0ebac", shape=hexagon, style=filled, color=green]; - "307E" [label="660ffeb76fc59", shape=box, style=filled, color=grey]; - 63 [label=a96e47ff37983425a3e452095, shape=hexagon, style=filled, color=green]; - "309E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 64 [label="71a48d11b2e7e56b1df128bd", shape=hexagon, style=filled, color=green]; - "311E" [label=be8f4199f, shape=box, style=filled, color=grey]; - 65 [label=a0befe6dd1ca7b165786835, shape=hexagon, style=filled, color=green]; - "313E" [label="3cfae", shape=box, style=filled, color=grey]; - 66 [label=f33ec11db496f7bfcb024f, shape=hexagon, style=filled, color=green]; - "315E" [label="71e6b", shape=box, style=filled, color=grey]; - 67 [label=fe6be3206549f5b5564acde84783, shape=hexagon, style=filled, color=green]; - "317E" [shape=box, style=filled, color=grey]; - 68 [label=e4dba079d5fcb1f165920a3bf, shape=hexagon, style=filled, color=green]; - "319E" [shape=box, style=filled, color=grey]; - 70 [label="16c508ab98483d430bbe", shape=hexagon, style=filled, color=green]; - "321E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 71 [label="9c9e2e0f2da8758e436c", shape=hexagon, style=filled, color=green]; - "327E" [label=cd0d985a366cad7e, shape=box, style=filled, color=grey]; - 72 [label=fb039d7a2a9fe73b5f468eba9, shape=hexagon, style=filled, color=green]; - "329E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 73 [label="2ef949c4a39b", shape=hexagon, style=filled, color=green]; - "331E" [label="617809d979f", shape=box, style=filled, color=grey]; - 74 [label=a9497e0757b0969bde707ed5, shape=hexagon, style=filled, color=green]; - "333E" [label="541ab86a2e", shape=box, style=filled, color=grey]; - 75 [label="230cc6bbc66b24eae94fa03d", shape=hexagon, style=filled, color=green]; - "335E" [shape=box, style=filled, color=grey]; - 76 [label="1d163eac141def176461c", shape=hexagon, style=filled, color=green]; - "337E" [label="0acc5bb8ca4", shape=box, style=filled, color=grey]; - 77 [label="32979f8cf86", shape=hexagon, style=filled, color=green]; - "339E" [label=a7e89580, shape=box, style=filled, color=grey]; - 78 [label="37d80ae421dba4a70730338860", shape=hexagon, style=filled, color=green]; - "341E" [shape=box, style=filled, color=grey]; - 79 [label=fbba7215e7c13173a60206, shape=hexagon, style=filled, color=green]; - "343E" [label="617809d979f", shape=box, style=filled, color=grey]; - 80 [label="2dd8cc4d693415f93c0f8fc", shape=hexagon, style=filled, color=green]; - "345E" [label="94da691e20e3", shape=box, style=filled, color=grey]; - 81 [label="00880e6f50c765ebc1f85d3e9", shape=hexagon, style=filled, color=green]; - "347E" [label=e7ef998, shape=box, style=filled, color=grey]; - 82 [label=ef13d45b1277ac9a0444adb, shape=hexagon, style=filled, color=green]; - "349E" [label=a7fe7, shape=box, style=filled, color=grey]; - 83 [label="2573e1bf51f1b307f4640", shape=hexagon, style=filled, color=green]; - "351E" [label="84e4ede82074", shape=box, style=filled, color=grey]; - 84 [label="162d8039483d8", shape=hexagon, style=filled, color=green]; - "353E" [label=a8e9, shape=box, style=filled, color=grey]; - 85 [label=f490de272a7f6e4af346d40, shape=hexagon, style=filled, color=green]; - "355E" [label="460aed10cc9", shape=box, style=filled, color=grey]; - "788E" [label="391256c872", shape=box, style=filled, color=grey]; - 86 [label="678bf739c344b9ad41da1", shape=hexagon, style=filled, color=green]; - "357E" [label="396b16a892fe", shape=box, style=filled, color=grey]; - 87 [label="876d120b38b0e88817", shape=hexagon, style=filled, color=green]; - "359E" [label=e5, shape=box, style=filled, color=grey]; - 88 [label="503737b64d432c60d6ac557e0e6", shape=hexagon, style=filled, color=green]; - "361E" [label="9937ccba1469", shape=box, style=filled, color=grey]; - 89 [label=b36e0be6f67fc25286127456, shape=hexagon, style=filled, color=green]; - "363E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; - 90 [label="4cc20a0b7651e486", shape=hexagon, style=filled, color=green]; - "365E" [label=e079d2c, shape=box, style=filled, color=grey]; - 91 [label="08dade990b2282", shape=hexagon, style=filled, color=green]; - "367E" [label="45827dbdd8", shape=box, style=filled, color=grey]; - 92 [label=f8128d574c356631b8a9, shape=hexagon, style=filled, color=green]; - "369E" [shape=box, style=filled, color=grey]; - 93 [label="88a4f0337c2189c3fc7b31", shape=hexagon, style=filled, color=green]; - "729E" [label=da0d7bbcf30, shape=box, style=filled, color=grey]; - 94 [label="1b13908a9f0763c0ae54af9062080", shape=hexagon, style=filled, color=green]; - "371E" [label="8b06a67a", shape=box, style=filled, color=grey]; - 95 [label=e2a5d11499b7e, shape=hexagon, style=filled, color=green]; - "373E" [label="66abc181ac4", shape=box, style=filled, color=grey]; - 96 [label="90cc275011c2013c61eb11", shape=hexagon, style=filled, color=green]; - "375E" [shape=box, style=filled, color=grey]; - 98 [label="1927c743a0d440a5a0", shape=hexagon, style=filled, color=green]; - "377E" [label=b12441ecff15fa12c, shape=box, style=filled, color=grey]; - 99 [label="155d892827c33ed3cae3", shape=hexagon, style=filled, color=green]; - "379E" [label="71e6b", shape=box, style=filled, color=grey]; - 100 [label="9f24ba80192c339a64c0", shape=hexagon, style=filled, color=green]; - "381E" [shape=box, style=filled, color=grey]; - 101 [label="3e814305b42beb41b8c706", shape=hexagon, style=filled, color=green]; - "383E" [label="1c08373", shape=box, style=filled, color=grey]; - 102 [label=eccfe5ff0af70fe9fbec8b2360f90, shape=hexagon, style=filled, color=green]; - "385E" [label=be8f4199f, shape=box, style=filled, color=grey]; - 103 [label="8fa622d9f842c5572a545ed72982", shape=hexagon, style=filled, color=green]; - "387E" [label="4dccb", shape=box, style=filled, color=grey]; - 104 [label=ad9142a65f5eab78b4ca5e, shape=hexagon, style=filled, color=green]; - "389E" [label=f36cce089, shape=box, style=filled, color=grey]; - 105 [label="20f234fdcd0e1fc50261ce8", shape=hexagon, style=filled, color=green]; - "391E" [label="67219ef689f0146b544", shape=box, style=filled, color=grey]; - 106 [label=e06cc38155ff6781cf944d745, shape=hexagon, style=filled, color=green]; - "393E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; - 107 [label=cfdf1932665dcb4cd3c, shape=hexagon, style=filled, color=green]; - "395E" [label="964b86fc1bba0e", shape=box, style=filled, color=grey]; - 108 [label="6d4a4a5a5af91b895272c30", shape=hexagon, style=filled, color=green]; - "397E" [label=b5e86c73d1198f, shape=box, style=filled, color=grey]; - 109 [label=e0ad365c2fb444358201, shape=hexagon, style=filled, color=green]; - "399E" [label=bb5e89c8963, shape=box, style=filled, color=grey]; - 110 [label=b07bbdc8cca5985d4c4, shape=hexagon, style=filled, color=green]; - "401E" [label="50023f6f88", shape=box, style=filled, color=grey]; - 111 [label=df5dba74c75b228de48c, shape=hexagon, style=filled, color=green]; - "403E" [label="7e493ee44b28", shape=box, style=filled, color=grey]; - 112 [label="0b8694c9ef9b27b9c3d8", shape=hexagon, style=filled, color=green]; - "405E" [label="2342b759c03", shape=box, style=filled, color=grey]; - 113 [label="81e20155999fa64e0ae6fd", shape=hexagon, style=filled, color=green]; - "407E" [label="4280833ef80172", shape=box, style=filled, color=grey]; - 114 [label="3ef07ae75d29a707", shape=hexagon, style=filled, color=green]; - "409E" [label="4280833ef80172", shape=box, style=filled, color=grey]; - 115 [label="4a36db80f1ab1e97", shape=hexagon, style=filled, color=green]; - "411E" [label="460aed10cc9", shape=box, style=filled, color=grey]; - 116 [label="16da5f1301b36df4df0f", shape=hexagon, style=filled, color=green]; - "413E" [label="460aed10cc9", shape=box, style=filled, color=grey]; - 117 [label="6b3f3fa236bb90592d23a", shape=hexagon, style=filled, color=green]; - "415E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; - 118 [label=f2a57e4d4f0cec516891e3, shape=hexagon, style=filled, color=green]; - "417E" [label=bd2484, shape=box, style=filled, color=grey]; - 119 [label=deb3089920548bf1ecb23f0d, shape=hexagon, style=filled, color=green]; - "419E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; - 120 [label=bf01c8a262, shape=hexagon, style=filled, color=green]; - "421E" [label=01, shape=box, style=filled, color=grey]; - 121 [label="23dc3a52fed9c119610b5e8", shape=hexagon, style=filled, color=green]; - "423E" [label="71e6b", shape=box, style=filled, color=grey]; - 123 [label="78cc16f965adc5f712ea2372c6", shape=hexagon, style=filled, color=green]; - "425E" [label="23ad1", shape=box, style=filled, color=grey]; - 124 [label="5be631dff7b97697be7dc0a2f07f2", shape=hexagon, style=filled, color=green]; - "427E" [shape=box, style=filled, color=grey]; - "786E" [label=421, shape=box, style=filled, color=grey]; - 125 [label="48398d080dfcccced48da1980", shape=hexagon, style=filled, color=green]; - "431E" [label="866808df", shape=box, style=filled, color=grey]; - 126 [label="03716a2c341e5edaa31", shape=hexagon, style=filled, color=green]; - "433E" [label="21407f8a6d7", shape=box, style=filled, color=grey]; - 127 [label=ddfeabe456a9de5f5784, shape=hexagon, style=filled, color=green]; - "435E" [label=aac615ae78, shape=box, style=filled, color=grey]; - 128 [label=d550a7f392c787661aadd48, shape=hexagon, style=filled, color=green]; - "437E" [label=e3aefac763, shape=box, style=filled, color=grey]; - 129 [label="4c82921f4ad3f07066540", shape=hexagon, style=filled, color=green]; - "439E" [label=a7fe7, shape=box, style=filled, color=grey]; - 130 [label="0bc7f8f513e0e74b270", shape=hexagon, style=filled, color=green]; - "441E" [label=a849f9d352e, shape=box, style=filled, color=grey]; - 131 [label="3b1563a23eb9", shape=hexagon, style=filled, color=green]; - "443E" [label=a8e9, shape=box, style=filled, color=grey]; - 132 [label=be233fafa38d931d894, shape=hexagon, style=filled, color=green]; - "445E" [label=a849f9d352e, shape=box, style=filled, color=grey]; - 134 [label=e7a887d88c2318beba51, shape=hexagon, style=filled, color=green]; - "447E" [label="9d8988c0945d6", shape=box, style=filled, color=grey]; - 135 [label=be6b73bd46a7a5183e8c91a, shape=hexagon, style=filled, color=green]; - "449E" [label=ee91c97828, shape=box, style=filled, color=grey]; - "769E" [label="444189d179b5db71fe", shape=box, style=filled, color=grey]; - "770E" [label="1e1fbbe14ac24e0518", shape=box, style=filled, color=grey]; - 136 [label="644f112bb0aa452ee7040a", shape=hexagon, style=filled, color=green]; - "451E" [label="52f247fc3b", shape=box, style=filled, color=grey]; - 137 [label="010957669f3770aac", shape=hexagon, style=filled, color=green]; - "453E" [label=78, shape=box, style=filled, color=grey]; - 138 [label="0a185946ee443342b07d8e1", shape=hexagon, style=filled, color=green]; - "455E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; - 139 [label=f66fe4df3d189e69ce10c9c, shape=hexagon, style=filled, color=green]; - "457E" [label="21407f8a6d7", shape=box, style=filled, color=grey]; - 140 [label="247e407f45b353f8", shape=hexagon, style=filled, color=green]; - "459E" [shape=box, style=filled, color=grey]; - 141 [label="84907547f36d0ff7", shape=hexagon, style=filled, color=green]; - "461E" [label=e920b915087, shape=box, style=filled, color=grey]; - 142 [label="805004328dad9d315d", shape=hexagon, style=filled, color=green]; - "463E" [label="4280833ef80172", shape=box, style=filled, color=grey]; - 143 [label="4f0cbd3fbf0cb1e8c", shape=hexagon, style=filled, color=green]; - "465E" [label=403126, shape=box, style=filled, color=grey]; - 144 [label="4869e993f2bb10f", shape=hexagon, style=filled, color=green]; - "467E" [label=ff, shape=box, style=filled, color=grey]; - 145 [label="665b76844ff78fc2cf66ca2", shape=hexagon, style=filled, color=green]; - "469E" [label=af0268dddd, shape=box, style=filled, color=grey]; - 146 [label="3f16509139c7dad5163b91799", shape=hexagon, style=filled, color=green]; - "471E" [label="3089106e3b", shape=box, style=filled, color=grey]; - 147 [label="01db23a60422ba93a68611cc0", shape=hexagon, style=filled, color=green]; - "473E" [shape=box, style=filled, color=grey]; - 148 [label="46125fcc583c0f494a3a1d3", shape=hexagon, style=filled, color=green]; - "475E" [label=db6c4213a717bc, shape=box, style=filled, color=grey]; - 149 [label="731857fe189fb398e80a0594", shape=hexagon, style=filled, color=green]; - "477E" [label="3089106e3b", shape=box, style=filled, color=grey]; - 150 [label="6fb7a84e370ef70feac5cb", shape=hexagon, style=filled, color=green]; - "479E" [label="396b16a892fe", shape=box, style=filled, color=grey]; - 151 [label=e343cea291b79a2ed4e, shape=hexagon, style=filled, color=green]; - "481E" [label="88d8b220746882d", shape=box, style=filled, color=grey]; - 152 [label="5f2592b20f13356b7fc8b42", shape=hexagon, style=filled, color=green]; - "483E" [shape=box, style=filled, color=grey]; - 153 [label="275a0407e33e9b8aa9cdd051", shape=hexagon, style=filled, color=green]; - "731E" [shape=box, style=filled, color=grey]; - 155 [label="173fd00917644f0f1f3e3", shape=hexagon, style=filled, color=green]; - "485E" [label="0acc5bb8ca4", shape=box, style=filled, color=grey]; - 156 [label=c72df69b40156a3254, shape=hexagon, style=filled, color=green]; - "487E" [label=fff03efcd, shape=box, style=filled, color=grey]; - 157 [label="6c632ad9c42228bb337", shape=hexagon, style=filled, color=green]; - "489E" [label=eb8, shape=box, style=filled, color=grey]; - 158 [label=bbb13dc62adf2de2a42b6, shape=hexagon, style=filled, color=green]; - "491E" [label="69ce90c9b2", shape=box, style=filled, color=grey]; - 159 [label="6282bc21f6", shape=hexagon, style=filled, color=green]; - "495E" [label=de34214b4c258c9333ec3, shape=box, style=filled, color=grey]; - 160 [label="71cf45dd4e91bcca945137b40e", shape=hexagon, style=filled, color=green]; - "499E" [label="65fd8495", shape=box, style=filled, color=grey]; - 161 [label=a3b6df27179b175c88fa4c9cf9f, shape=hexagon, style=filled, color=green]; - "501E" [label=6577, shape=box, style=filled, color=grey]; - 162 [label="284f14a259991806654e74", shape=hexagon, style=filled, color=green]; - "503E" [label="4280833ef80172", shape=box, style=filled, color=grey]; - 163 [label=a7c99ccf6ddf6f5ebbe, shape=hexagon, style=filled, color=green]; - "505E" [label=c4fd8, shape=box, style=filled, color=grey]; - 164 [label=c32d2697e8, shape=hexagon, style=filled, color=green]; - "507E" [label="52f247fc3b", shape=box, style=filled, color=grey]; - 165 [label=d12bd75c24b110ef90cdd35d3, shape=hexagon, style=filled, color=green]; - "509E" [label=0668, shape=box, style=filled, color=grey]; - 166 [label="1c07453d584f3d14b1876fdb", shape=hexagon, style=filled, color=green]; - "511E" [label="460aed10cc9", shape=box, style=filled, color=grey]; - 167 [label=f713a8b311ffa05ce3683ad10, shape=hexagon, style=filled, color=green]; - "513E" [label="30d6138b63eb", shape=box, style=filled, color=grey]; - 168 [label="3cdc90c57243373efaba65a", shape=hexagon, style=filled, color=green]; - "515E" [label=fa2afbd869, shape=box, style=filled, color=grey]; - 169 [label=e3bdbca0e2256fffa8a59018, shape=hexagon, style=filled, color=green]; - "517E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 170 [label="75ba8d840070942eb4e737849", shape=hexagon, style=filled, color=green]; - "519E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 171 [label=fbdc3ca37406f66635c8b226e, shape=hexagon, style=filled, color=green]; - "521E" [label="8cbcf5cb5", shape=box, style=filled, color=grey]; - 172 [label="40b49a5a9bb256c7a3286e56", shape=hexagon, style=filled, color=green]; - "523E" [label=f72564578be, shape=box, style=filled, color=grey]; - 173 [label="3b2f08d52e4bca3f9ca7bbbd6", shape=hexagon, style=filled, color=green]; - "525E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 174 [label="4a38abc630c82b0c48dfbf5271", shape=hexagon, style=filled, color=green]; - "527E" [label=f0bd1521, shape=box, style=filled, color=grey]; - 175 [label="2d7b7fb6c9ad6821752651f7", shape=hexagon, style=filled, color=green]; - "529E" [label="47b2da3d", shape=box, style=filled, color=grey]; - 176 [label="910b00285f11bb90d0a15641", shape=hexagon, style=filled, color=green]; - "531E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 177 [label="24431c3eb075102f07cc2c1be", shape=hexagon, style=filled, color=green]; - "533E" [shape=box, style=filled, color=grey]; - 178 [label="07f8a9e55a16beddb3c9153b0", shape=hexagon, style=filled, color=green]; - "535E" [label="81dabfaba8", shape=box, style=filled, color=grey]; - 179 [label=c1c30f30d40c4f1f84924622f, shape=hexagon, style=filled, color=green]; - "537E" [label=c5d5be3942, shape=box, style=filled, color=grey]; - 180 [label="86276bb1e23f2c7ffcbe82a0", shape=hexagon, style=filled, color=green]; - "539E" [label="0f940646", shape=box, style=filled, color=grey]; - 181 [label=f78e145a127014eb43345a0c, shape=hexagon, style=filled, color=green]; - "541E" [label=d370c12dbc, shape=box, style=filled, color=grey]; - 182 [label=a27037332d9fa5c43bcfe94c0, shape=hexagon, style=filled, color=green]; - "543E" [label="80874aa8", shape=box, style=filled, color=grey]; - 183 [label=c29ce10bb8d19b498355aa04, shape=hexagon, style=filled, color=green]; - "545E" [label="1c08373", shape=box, style=filled, color=grey]; - 184 [label="4f8c642b53c349c687534bda35db", shape=hexagon, style=filled, color=green]; - "547E" [label="46969c4", shape=box, style=filled, color=grey]; - 185 [label="30cc206b1878485", shape=hexagon, style=filled, color=green]; - "549E" [label="23ad1", shape=box, style=filled, color=grey]; - 186 [label="5d69639a5e3bdd3d", shape=hexagon, style=filled, color=green]; - "551E" [label="6139fa6adc88d", shape=box, style=filled, color=grey]; - 187 [label=b656f0ed2202b8e46eb, shape=hexagon, style=filled, color=green]; - "553E" [label=f6e6236b48bc3, shape=box, style=filled, color=grey]; - 188 [label="3b566eaa70ed401479d43a9", shape=hexagon, style=filled, color=green]; - "555E" [label="4c6c8c", shape=box, style=filled, color=grey]; - 189 [label=d6125ef42bd9958, shape=hexagon, style=filled, color=green]; - "557E" [label="4c6c8c", shape=box, style=filled, color=grey]; - 190 [label=dd12f26f8d9bb55, shape=hexagon, style=filled, color=green]; - "559E" [label="83c397b8bf7f", shape=box, style=filled, color=grey]; - 191 [label=ea890ccca2f7c2107351, shape=hexagon, style=filled, color=green]; - "561E" [label=eb8, shape=box, style=filled, color=grey]; - 192 [label="84e4f1c582427a98d7b", shape=hexagon, style=filled, color=green]; - "563E" [label=eb8, shape=box, style=filled, color=grey]; - 193 [label=d378760b814eaecb6efe636e0efc4, shape=hexagon, style=filled, color=green]; - "565E" [label="81bcc35f82891", shape=box, style=filled, color=grey]; - 194 [label=f722890f70a32dce3baff371a, shape=hexagon, style=filled, color=green]; - "567E" [label="84e4ede82074", shape=box, style=filled, color=grey]; - 195 [label="666f11bb45c3a8dcf26e1ed79", shape=hexagon, style=filled, color=green]; - "569E" [label=c90f755c8b6612d, shape=box, style=filled, color=grey]; - 196 [label="91ecbe29a71f00ed5a3", shape=hexagon, style=filled, color=green]; - "571E" [label="0a963fef9", shape=box, style=filled, color=grey]; - 197 [label="30c3f3bf8463d3843dc57d8e98", shape=hexagon, style=filled, color=green]; - "573E" [label="3089106e3b", shape=box, style=filled, color=grey]; - 198 [label="8ea965ab6ee8dedb6c3333e9", shape=hexagon, style=filled, color=green]; - "575E" [label="84e4ede82074", shape=box, style=filled, color=grey]; - 199 [label="3eecb304bab2136a76deda", shape=hexagon, style=filled, color=green]; - "577E" [label="8df", shape=box, style=filled, color=grey]; - 200 [label=d886e4b76537a99bc71b8a9331c94, shape=hexagon, style=filled, color=green]; - "579E" [label="1172dca23", shape=box, style=filled, color=grey]; - 201 [label=dcc5d5e9d6c4e, shape=hexagon, style=filled, color=green]; - "581E" [label=a8e9, shape=box, style=filled, color=grey]; - 202 [label="8292af691429f8d9ed481ff71ffd", shape=hexagon, style=filled, color=green]; - "583E" [label="212af4", shape=box, style=filled, color=grey]; - 203 [label="12fcb26b3de00ef98719c2ca", shape=hexagon, style=filled, color=green]; - "585E" [shape=box, style=filled, color=grey]; - 204 [label=a141a557a60912051f3c135, shape=hexagon, style=filled, color=green]; - "587E" [shape=box, style=filled, color=grey]; - 206 [label=f5d636e14a6cd716362158d, shape=hexagon, style=filled, color=green]; - "589E" [label="32c958c9997", shape=box, style=filled, color=grey]; - 208 [label="52a6c2063bccd83110c32", shape=hexagon, style=filled, color=green]; - "597E" [shape=box, style=filled, color=grey]; - 209 [label="46f754ea06f070dbc023e571a876", shape=hexagon, style=filled, color=green]; - "599E" [label=ffccaa9e3, shape=box, style=filled, color=grey]; - 210 [label=c10cb9baf4dcb43e24, shape=hexagon, style=filled, color=green]; - "601E" [label=ac6e99186, shape=box, style=filled, color=grey]; - 211 [label="3dafe1619016463f521f", shape=hexagon, style=filled, color=green]; - "603E" [label=b9, shape=box, style=filled, color=grey]; - 212 [label="0f5db6ce12751ddcc64e", shape=hexagon, style=filled, color=green]; - "605E" [label=bb828f1a326, shape=box, style=filled, color=grey]; - 213 [label="34c8c8dc0f6e41c7e7b2", shape=hexagon, style=filled, color=green]; - "607E" [label="2832ed5cea6", shape=box, style=filled, color=grey]; - 214 [label="0a49c95f107c0aa57c9b5748", shape=hexagon, style=filled, color=green]; - "609E" [shape=box, style=filled, color=grey]; - 215 [label="3b4fdad8e0429d112", shape=hexagon, style=filled, color=green]; - "611E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 216 [label="17dafa5ebaafd48440e3", shape=hexagon, style=filled, color=green]; - "613E" [label=b5f038f79a3, shape=box, style=filled, color=grey]; - 217 [label=f4c69e5e212f89348122e8, shape=hexagon, style=filled, color=green]; - "615E" [label="396b16a892fe", shape=box, style=filled, color=grey]; - 218 [label="4f2e020854dfacce46a12", shape=hexagon, style=filled, color=green]; - "617E" [label=e079d2c, shape=box, style=filled, color=grey]; - 219 [label="6448451ac2ceade90715378b", shape=hexagon, style=filled, color=green]; - "619E" [shape=box, style=filled, color=grey]; - 221 [label=d7c27cc6f7b02a31eb64d, shape=hexagon, style=filled, color=green]; - "623E" [label="87a7e69a72412", shape=box, style=filled, color=grey]; - 223 [label=eccf7c722ddf, shape=hexagon, style=filled, color=green]; - "625E" [label=df61d5f5fc, shape=box, style=filled, color=grey]; - 224 [label="86633c26be93ada8b", shape=hexagon, style=filled, color=green]; - "627E" [label="08500a6044", shape=box, style=filled, color=grey]; - 225 [label="3f9ddf1ffbc0d38b", shape=hexagon, style=filled, color=green]; - "629E" [label=07, shape=box, style=filled, color=grey]; - 226 [label=e33792703, shape=hexagon, style=filled, color=green]; - "631E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; - 227 [label="293a225dc56dd1e0564e6bb", shape=hexagon, style=filled, color=green]; - "633E" [label=e3aefac763, shape=box, style=filled, color=grey]; - 228 [label="57c77c341f94afddef07e6", shape=hexagon, style=filled, color=green]; - "635E" [label="5e80f85274", shape=box, style=filled, color=grey]; - 229 [label="3bbfc7bfdbbb1ba1bfad7517", shape=hexagon, style=filled, color=green]; - "637E" [shape=box, style=filled, color=grey]; - 230 [label=a7167d5eb5408b3839903, shape=hexagon, style=filled, color=green]; - "639E" [label="8c8b5bde6", shape=box, style=filled, color=grey]; - 231 [label="34d7bb6af4fcd8d630de72500c8", shape=hexagon, style=filled, color=green]; - "641E" [label="32fe7eee5283", shape=box, style=filled, color=grey]; - 232 [label="8e69341faa4489", shape=hexagon, style=filled, color=green]; - "643E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 233 [label="459236f07c73814faf5", shape=hexagon, style=filled, color=green]; - "645E" [label="18083a711d", shape=box, style=filled, color=grey]; - 234 [label=c71aa521578164debd0c5, shape=hexagon, style=filled, color=green]; - "647E" [label=78, shape=box, style=filled, color=grey]; - 235 [label=a5520019b8a73bc141b5fd416a, shape=hexagon, style=filled, color=green]; - "649E" [label="3219b6b71443", shape=box, style=filled, color=grey]; - 236 [label="6c89dc59ee7aaebbbd6bb64", shape=hexagon, style=filled, color=green]; - "651E" [label="8c8b5bde6", shape=box, style=filled, color=grey]; - 237 [label=a9a36ef02f, shape=hexagon, style=filled, color=green]; - "653E" [label="6a80cbe", shape=box, style=filled, color=grey]; - 238 [label="3db761b596844f133c", shape=hexagon, style=filled, color=green]; - "655E" [label=e920b915087, shape=box, style=filled, color=grey]; - 239 [label="383db224d7508ef072bea21d0", shape=hexagon, style=filled, color=green]; - "657E" [label="975fedfb64df", shape=box, style=filled, color=grey]; - 240 [label="8e307415fb435445ced7", shape=hexagon, style=filled, color=green]; - "659E" [label="21dff35936370ae5f", shape=box, style=filled, color=grey]; - 241 [label=aff6d7896e0e142bbc3e78, shape=hexagon, style=filled, color=green]; - "661E" [label=d2498, shape=box, style=filled, color=grey]; - 242 [label=e153c6e676c7369b285b4e9033a, shape=hexagon, style=filled, color=green]; - "663E" [shape=box, style=filled, color=grey]; - 243 [label=f3c4311de0e931f08c232b, shape=hexagon, style=filled, color=green]; - "665E" [label=a849f9d352e, shape=box, style=filled, color=grey]; - 244 [label="0c72a426929600000f5", shape=hexagon, style=filled, color=green]; - "667E" [label="45827dbdd8", shape=box, style=filled, color=grey]; - 245 [label="38fa61352f5086d2cb51", shape=hexagon, style=filled, color=green]; - "669E" [label=af0268dddd, shape=box, style=filled, color=grey]; - 246 [label=ad1dd724f1c3e, shape=hexagon, style=filled, color=green]; - "671E" [label=cab04b7c14a, shape=box, style=filled, color=grey]; - 247 [label="11bb8ed3ae227d3acefc", shape=hexagon, style=filled, color=green]; - "673E" [label=eb8, shape=box, style=filled, color=grey]; - 248 [label=f2c7b3bb4d44f977d0ab8a42351, shape=hexagon, style=filled, color=green]; - "675E" [shape=box, style=filled, color=grey]; - 249 [label="51e045ca826077ae765", shape=hexagon, style=filled, color=green]; - "679E" [label=e842, shape=box, style=filled, color=grey]; - 251 [label="3b6b2c549de670d7bf5fc0ee", shape=hexagon, style=filled, color=green]; - "681E" [shape=box, style=filled, color=grey]; - 252 [label="5eea496cc301b2a9721", shape=hexagon, style=filled, color=green]; - "683E" [shape=box, style=filled, color=grey]; - 253 [label=bfc6564cbdeeffac00a141, shape=hexagon, style=filled, color=green]; - "685E" [label="3b0a8a1c2e5050bd", shape=box, style=filled, color=grey]; - 254 [label=c360aaeb167487c9578a8f, shape=hexagon, style=filled, color=green]; - "687E" [label=d, shape=box, style=filled, color=grey]; - 255 [label="39d025b265f9790490781cb201", shape=hexagon, style=filled, color=green]; - "689E" [label="5e80f85274", shape=box, style=filled, color=grey]; - 256 [label=b4ce21e0a3df1d097277d6, shape=hexagon, style=filled, color=green]; - "691E" [label=a849f9d352e, shape=box, style=filled, color=grey]; - 257 [label="8bdb6a91c6dee925b557c705b3", shape=hexagon, style=filled, color=green]; - "693E" [label="53069e384a2", shape=box, style=filled, color=grey]; - 258 [label=ac487676a04e4, shape=hexagon, style=filled, color=green]; - "695E" [label=a8e9, shape=box, style=filled, color=grey]; - 259 [label="18115fa32ff1cb99", shape=hexagon, style=filled, color=green]; - "697E" [label="45827dbdd8", shape=box, style=filled, color=grey]; - 260 [label=b7b899dc8bc6a32b28cb098fa16, shape=hexagon, style=filled, color=green]; - "699E" [label="32fe7eee5283", shape=box, style=filled, color=grey]; - 261 [label=b69e426d974e1907e88, shape=hexagon, style=filled, color=green]; - "703E" [label=e842, shape=box, style=filled, color=grey]; - 262 [label="60d0128bdb61ae40e98638bd1391", shape=hexagon, style=filled, color=green]; - "705E" [label="23ad1", shape=box, style=filled, color=grey]; - 264 [label="8fb60d769e4c387", shape=hexagon, style=filled, color=green]; - "709E" [label="6a8f5bafb1", shape=box, style=filled, color=grey]; - 265 [label=e1fa7f549e5a0893bb42da5, shape=hexagon, style=filled, color=green]; - "711E" [label="6a3c6921b0aeceda3", shape=box, style=filled, color=grey]; - 266 [label=a77622f2ff77ffeeb2, shape=hexagon, style=filled, color=green]; - "713E" [label="21dff35936370ae5f", shape=box, style=filled, color=grey]; - 267 [label="30d9d350943c0e3ff7594b50", shape=hexagon, style=filled, color=green]; - "715E" [label=b5e86c73d1198f, shape=box, style=filled, color=grey]; - 268 [label="89ced1a7906d58d687d5a04", shape=hexagon, style=filled, color=green]; - "717E" [label=c0174bbe7ae8, shape=box, style=filled, color=grey]; - 269 [label="1de26f6b12b0d292f94184", shape=hexagon, style=filled, color=green]; - "719E" [label="65fd8495", shape=box, style=filled, color=grey]; - 270 [label="26fa7360ab81be9d4434a", shape=hexagon, style=filled, color=green]; - "721E" [label=af0268dddd, shape=box, style=filled, color=grey]; - 272 [label="4a9d79c960b8d33e39251e5f66", shape=hexagon]; - "34E" [label="330342f283ef2", shape=box, style=filled, color=grey]; - "252E" [label="3dafb9a29c00", shape=box, style=filled, color=grey]; - "436E" [label="8d5137b16a", shape=box, style=filled, color=grey]; - 274 [label="10a7d61c201c67a5e78542807cd", shape=hexagon]; - "59E" [label=ef6361295eba07, shape=box, style=filled, color=grey]; - "500E" [label=a8f0fe2eb7bc1471, shape=box, style=filled, color=grey]; - "720E" [label=cfff3acd8e9d, shape=box, style=filled, color=grey]; - 275 [label=f8ff39eab120851f143bf19, shape=hexagon]; - "98E" [label="4e3cfd27a", shape=box, style=filled, color=grey]; - 278 [label="4995c71223c9f6067324d387a2", shape=hexagon]; - "35E" [label="57948adb5dead", shape=box, style=filled, color=grey]; - "488E" [label=a738ba39, shape=box, style=filled, color=grey]; - "598E" [label=be7d637c50c, shape=box, style=filled, color=grey]; - "604E" [label="8d52f183ec", shape=box, style=filled, color=grey]; - "628E" [label=cef12b6, shape=box, style=filled, color=grey]; - 279 [label=b9ae94e6935503603341ecf4, shape=hexagon]; - "99E" [label="14a3c17f3d", shape=box, style=filled, color=grey]; - 280 [label=fd28c194a46fde909b019c52f, shape=hexagon]; - "242E" [label="9fe65061641", shape=box, style=filled, color=grey]; - "270E" [label="34d06d1ed6", shape=box, style=filled, color=grey]; - "272E" [label="713db1c1", shape=box, style=filled, color=grey]; - "284E" [label="90dccb18c0", shape=box, style=filled, color=grey]; - "286E" [label=e17fea65, shape=box, style=filled, color=grey]; - "288E" [label=aebb7b91b, shape=box, style=filled, color=grey]; - "586E" [label="4348f3abcb7716", shape=box, style=filled, color=grey]; - "763E" [label=b082f7a5ff, shape=box, style=filled, color=grey]; - 281 [label="7c0ab977f5a3c4ab6d625f5033", shape=hexagon]; - "45E" [label="20949455f573f", shape=box, style=filled, color=grey]; - "470E" [label=c338481d79773, shape=box, style=filled, color=grey]; - "670E" [label=e1d01ef89f, shape=box, style=filled, color=grey]; - "722E" [label=c4507c22d19, shape=box, style=filled, color=grey]; - 282 [label="7e0b91491c8c8566892cd9a0889", shape=hexagon]; - "103E" [label=de9efa12873949, shape=box, style=filled, color=grey]; - 283 [label=d58478d9c273ad4f4b2e091324, shape=hexagon]; - "165E" [label="1a220eb692c", shape=box, style=filled, color=grey]; - 284 [label="8be0efdd94a6383e87fbfded4f", shape=hexagon]; - "39E" [label=c8a6c26d4fd9f, shape=box, style=filled, color=grey]; - "224E" [label="8cbae42a3900", shape=box, style=filled, color=grey]; - "268E" [label=fc73, shape=box, style=filled, color=grey]; - "632E" [shape=box, style=filled, color=grey]; - "710E" [label="102f1", shape=box, style=filled, color=grey]; - 285 [label="3aeb78ea51020a44f2d2615436dae", shape=hexagon]; - "53E" [label="96deede0c6b44119", shape=box, style=filled, color=grey]; - 286 [label="6bbd5b422edb8e358dcc20eecf9", shape=hexagon]; - "38E" [label="4f2de229621272", shape=box, style=filled, color=grey]; - "166E" [label=d495de0b35f6, shape=box, style=filled, color=grey]; - 288 [label="4856000a6802ddfc121ef40432297", shape=hexagon, style=filled, color="#ff0000"]; - "40E" [label="04904a458422a5b9", shape=box, style=filled, color=grey]; - "218E" [label="8cd4d", shape=box, style=filled, color=grey]; - "244E" [shape=box, style=filled, color=grey]; - "246E" [label="9be88247", shape=box, style=filled, color=grey]; - "258E" [label="4f05b", shape=box, style=filled, color=grey]; - "290E" [label="8b092", shape=box, style=filled, color=grey]; - "292E" [label=c3bbf4, shape=box, style=filled, color=grey]; - "308E" [label="6331b3f", shape=box, style=filled, color=grey]; - "318E" [shape=box, style=filled, color=grey]; - "388E" [label=3711, shape=box, style=filled, color=grey]; - "472E" [label=c5255d, shape=box, style=filled, color=grey]; - "478E" [label="5c6a2", shape=box, style=filled, color=grey]; - "566E" [label="51ec95518d1b3", shape=box, style=filled, color=grey]; - "570E" [label="82a65ed4b69", shape=box, style=filled, color=grey]; - "574E" [label="05fed5e", shape=box, style=filled, color=grey]; - "608E" [label=bf, shape=box, style=filled, color=grey]; - "614E" [label=ce, shape=box, style=filled, color=grey]; - "658E" [label="1a830d9f", shape=box, style=filled, color=grey]; - "664E" [shape=box, style=filled, color=grey]; - "682E" [shape=box, style=filled, color=grey]; - 289 [label="2e31175cbd52fcd08360fe86d20", shape=hexagon]; - "41E" [label="4ad5d68f07981a", shape=box, style=filled, color=grey]; - "636E" [label="51192117f9b4", shape=box, style=filled, color=grey]; - "642E" [label="6bf214d9e7fa5f2df", shape=box, style=filled, color=grey]; - "690E" [label="558d8534f92fddfe", shape=box, style=filled, color=grey]; - "700E" [label="6819fd5a6cdd280dd", shape=box, style=filled, color=grey]; - 290 [label="3aa0ce5efcf79bc3ecced1886e89", shape=hexagon]; - "56E" [label=ff9d64ddf49a20f, shape=box, style=filled, color=grey]; - "264E" [label="6c93f24516f01d", shape=box, style=filled, color=grey]; - "510E" [label="32b98f11f3d01d6", shape=box, style=filled, color=grey]; - "718E" [label="8f7c875500073", shape=box, style=filled, color=grey]; - 291 [label="7c1767485953d9c2", shape=hexagon]; - "66E" [label=086, shape=box, style=filled, color=grey]; - "76E" [shape=box, style=filled, color=grey]; - "610E" [label="450d3a2d49cbfd", shape=box, style=filled, color=grey]; - 292 [label="9c1305d59c37e9be9f13d7d049c", shape=hexagon]; - "73E" [label=817, shape=box, style=filled, color=grey]; - 293 [label=efe092824916a5637ee35d439589, shape=hexagon]; - "49E" [shape=box, style=filled, color=grey]; - "214E" [shape=box, style=filled, color=grey]; - "216E" [shape=box, style=filled, color=grey]; - "236E" [shape=box, style=filled, color=grey]; - "278E" [shape=box, style=filled, color=grey]; - "358E" [shape=box, style=filled, color=grey]; - "398E" [shape=box, style=filled, color=grey]; - "400E" [shape=box, style=filled, color=grey]; - "402E" [shape=box, style=filled, color=grey]; - "404E" [shape=box, style=filled, color=grey]; - "406E" [shape=box, style=filled, color=grey]; - "408E" [shape=box, style=filled, color=grey]; - "412E" [shape=box, style=filled, color=grey]; - "438E" [shape=box, style=filled, color=grey]; - "448E" [shape=box, style=filled, color=grey]; - "476E" [shape=box, style=filled, color=grey]; - "504E" [shape=box, style=filled, color=grey]; - "552E" [shape=box, style=filled, color=grey]; - "634E" [shape=box, style=filled, color=grey]; - "768E" [shape=box, style=filled, color=grey]; - 295 [label="70815f0352b43dc1562133ab6eb", shape=hexagon, style=filled, color="#A52A2A"]; - "44E" [label=ef2d4636934472, shape=box, style=filled, color=grey]; - "92E" [label="22bd92e302816", shape=box, style=filled, color=grey]; - "250E" [label="74e86", shape=box, style=filled, color=grey]; - "316E" [shape=box, style=filled, color=grey]; - "380E" [shape=box, style=filled, color=grey]; - "424E" [label=c, shape=box, style=filled, color=grey]; - "442E" [label=a5a, shape=box, style=filled, color=grey]; - "446E" [label=bce, shape=box, style=filled, color=grey]; - "454E" [shape=box, style=filled, color=grey]; - "460E" [shape=box, style=filled, color=grey]; - "462E" [shape=box, style=filled, color=grey]; - "648E" [shape=box, style=filled, color=grey]; - "656E" [label=e9, shape=box, style=filled, color=grey]; - "666E" [label=b701e7, shape=box, style=filled, color=grey]; - "692E" [label=f2e7cc, shape=box, style=filled, color=grey]; - "712E" [label="8a9eb2806b0aa", shape=box, style=filled, color=grey]; - 296 [label=e287d497450664a4c0f4efc338, shape=hexagon, style=filled, color="#ff0000"]; - "47E" [label="06eff1db45cdf", shape=box, style=filled, color=grey]; - "330E" [label=c0f34a600, shape=box, style=filled, color=grey]; - "514E" [label=bd7aca295ca, shape=box, style=filled, color=grey]; - "516E" [label="0da9135", shape=box, style=filled, color=grey]; - "518E" [label=fe821bce, shape=box, style=filled, color=grey]; - "520E" [label=e64f22a31, shape=box, style=filled, color=grey]; - "522E" [label="46e412a3", shape=box, style=filled, color=grey]; - "526E" [label="99da1f8a5", shape=box, style=filled, color=grey]; - "528E" [label="0f167280", shape=box, style=filled, color=grey]; - "530E" [label="82d201", shape=box, style=filled, color=grey]; - "532E" [label="1d529eb4", shape=box, style=filled, color=grey]; - "534E" [shape=box, style=filled, color=grey]; - "536E" [label=bf141dbce, shape=box, style=filled, color=grey]; - "538E" [label=e3fd0c7b3, shape=box, style=filled, color=grey]; - "540E" [label=c96cb3, shape=box, style=filled, color=grey]; - "542E" [label="0fabab47", shape=box, style=filled, color=grey]; - "544E" [label="1b82200", shape=box, style=filled, color=grey]; - 297 [label="2ced414a91575a48f2dd29a", shape=hexagon]; - "46E" [label="85221d5e9e", shape=box, style=filled, color=grey]; - "93E" [label="97a7eea3f", shape=box, style=filled, color=grey]; - "206E" [label="4d22e1", shape=box, style=filled, color=grey]; - "426E" [label=e65185ca, shape=box, style=filled, color=grey]; - "550E" [shape=box, style=filled, color=grey]; - "706E" [label=a9012b7bb5, shape=box, style=filled, color=grey]; - 298 [label="38f162cf917ce7298663a1f1c607", shape=hexagon]; - "36E" [label=a031c9192ae8e75, shape=box, style=filled, color=grey]; - "95E" [label="062fc905b9eb35", shape=box, style=filled, color=grey]; - "364E" [label=c8fc17180bea86, shape=box, style=filled, color=grey]; - "394E" [label="09e64744536c5e1", shape=box, style=filled, color=grey]; - "420E" [label=af4a1fac3e2076, shape=box, style=filled, color=grey]; - "456E" [label="238805e2194c3", shape=box, style=filled, color=grey]; - "624E" [label="73e6ed83012", shape=box, style=filled, color=grey]; - 299 [label="549fa15d68f0b3bee6192f888cd8", shape=hexagon]; - "48E" [label=d17f8f4eeb8e63d, shape=box, style=filled, color=grey]; - "168E" [label=cca7040e47789, shape=box, style=filled, color=grey]; - "260E" [label="47ebc3f17", shape=box, style=filled, color=grey]; - "282E" [label=cf5a6049ad, shape=box, style=filled, color=grey]; - "554E" [label="2a47a6a27", shape=box, style=filled, color=grey]; - "590E" [label=eff3468631dd4, shape=box, style=filled, color=grey]; - "767E" [label=efb52b499303115c33fd, shape=box, style=filled, color=grey]; - 300 [label="8593dcf973b110d00cecdc1e756", shape=hexagon, style=filled, color="#ff7f00"]; - "62E" [label="472a156cf2b55f", shape=box, style=filled, color=grey]; - "190E" [label=647, shape=box, style=filled, color=grey]; - "226E" [shape=box, style=filled, color=grey]; - "238E" [label="8a", shape=box, style=filled, color=grey]; - "254E" [shape=box, style=filled, color=grey]; - "256E" [shape=box, style=filled, color=grey]; - "262E" [shape=box, style=filled, color=grey]; - "266E" [label=e8b, shape=box, style=filled, color=grey]; - "274E" [shape=box, style=filled, color=grey]; - "276E" [label=f, shape=box, style=filled, color=grey]; - "294E" [shape=box, style=filled, color=grey]; - "296E" [shape=box, style=filled, color=grey]; - "310E" [label="1b34fb150", shape=box, style=filled, color=grey]; - "320E" [shape=box, style=filled, color=grey]; - "322E" [label=a7d2, shape=box, style=filled, color=grey]; - "332E" [shape=box, style=filled, color=grey]; - "340E" [shape=box, style=filled, color=grey]; - "344E" [label=f55670, shape=box, style=filled, color=grey]; - "346E" [label="1ed67841", shape=box, style=filled, color=grey]; - "348E" [label=07283, shape=box, style=filled, color=grey]; - "374E" [label="73ba1714ee", shape=box, style=filled, color=grey]; - "378E" [label=27709106, shape=box, style=filled, color=grey]; - "452E" [label="93ea0", shape=box, style=filled, color=grey]; - "508E" [shape=box, style=filled, color=grey]; - "524E" [label="1d792d81", shape=box, style=filled, color=grey]; - "612E" [label=a, shape=box, style=filled, color=grey]; - "626E" [shape=box, style=filled, color=grey]; - "638E" [shape=box, style=filled, color=grey]; - "644E" [shape=box, style=filled, color=grey]; - "654E" [shape=box, style=filled, color=grey]; - "672E" [shape=box, style=filled, color=grey]; - 302 [label="23f94655294d3ff537f2915fa", shape=hexagon]; - "797E" [shape=box, style=filled, color=grey]; - "798E" [label=a2eab7c9fa641e5f, shape=box, style=filled, color=grey]; - 303 [label=a9058241db5b6b6c25569acdf5, shape=hexagon]; - "52E" [label=b2babf3244213, shape=box, style=filled, color=grey]; - "650E" [label=b354cd9e9dbb0bfa, shape=box, style=filled, color=grey]; - 304 [label=bdbdb31bd777fb65dd6dd2d0e7, shape=hexagon]; - "50E" [label="3bec1c012b498", shape=box, style=filled, color=grey]; - "640E" [label=c54f0fc1e05, shape=box, style=filled, color=grey]; - "646E" [label="9ab6c66dc", shape=box, style=filled, color=grey]; - "652E" [label="699e3db878047", shape=box, style=filled, color=grey]; - 306 [label="1d4ea80c7194689d69f9592186", shape=hexagon]; - "55E" [label="8066f87a88f4e", shape=box, style=filled, color=grey]; - "220E" [label="3a8173d6c", shape=box, style=filled, color=grey]; - "338E" [label="24dfe1a997a", shape=box, style=filled, color=grey]; - "368E" [label="65a1", shape=box, style=filled, color=grey]; - "486E" [label="59a8b435ccd", shape=box, style=filled, color=grey]; - "490E" [label="86e9b0428", shape=box, style=filled, color=grey]; - "562E" [label="5a7a610a8a", shape=box, style=filled, color=grey]; - "564E" [label="8f143077e", shape=box, style=filled, color=grey]; - "600E" [label="6472c2861e0e0dd681", shape=box, style=filled, color=grey]; - "668E" [label=f0f45e707, shape=box, style=filled, color=grey]; - "674E" [label="95e93c4a13", shape=box, style=filled, color=grey]; - "698E" [label="33e1de", shape=box, style=filled, color=grey]; - 307 [label="7204950f6233bf9c9e1f00d4a870", shape=hexagon]; - "107E" [label=ccceeef40edda78, shape=box, style=filled, color=grey]; - 308 [label=a2c4b1d72e2da483a86ae0c62e5, shape=hexagon]; - "108E" [label=eedc819a68add6, shape=box, style=filled, color=grey]; - 309 [label=f603819d560c5603259aa05dca, shape=hexagon]; - "109E" [label=acacfc83af504, shape=box, style=filled, color=grey]; - 310 [label="2f43cba12702078b4e0d3bfdae2bc", shape=hexagon]; - "110E" [label="3c1edc8de4795936", shape=box, style=filled, color=grey]; - 311 [label="8f9cdc26798117dd3e9ee4a8770", shape=hexagon]; - "58E" [label="881d373", shape=box, style=filled, color=grey]; - "234E" [shape=box, style=filled, color=grey]; - "300E" [shape=box, style=filled, color=grey]; - "306E" [label="8c7cd9b93b1cbe48e1", shape=box, style=filled, color=grey]; - "314E" [label="616d8a7b", shape=box, style=filled, color=grey]; - "342E" [shape=box, style=filled, color=grey]; - "354E" [shape=box, style=filled, color=grey]; - "370E" [shape=box, style=filled, color=grey]; - "382E" [shape=box, style=filled, color=grey]; - "422E" [shape=box, style=filled, color=grey]; - "444E" [shape=box, style=filled, color=grey]; - "582E" [shape=box, style=filled, color=grey]; - "620E" [shape=box, style=filled, color=grey]; - "630E" [shape=box, style=filled, color=grey]; - "684E" [shape=box, style=filled, color=grey]; - "696E" [shape=box, style=filled, color=grey]; - "801E" [shape=box, style=filled, color=grey]; - 312 [label="97c9d726e27304311901a52ce", shape=hexagon, style=filled, color="#ff0000"]; - "42E" [label="1112164c2f7a", shape=box, style=filled, color=grey]; - "192E" [label="5c609b12c", shape=box, style=filled, color=grey]; - "194E" [label=00265, shape=box, style=filled, color=grey]; - "196E" [label=04767, shape=box, style=filled, color=grey]; - "198E" [label=f0d99f16, shape=box, style=filled, color=grey]; - "200E" [shape=box, style=filled, color=grey]; - "202E" [label="6e186b", shape=box, style=filled, color=grey]; - "204E" [label=d382, shape=box, style=filled, color=grey]; - "312E" [label=c6b5321a, shape=box, style=filled, color=grey]; - "336E" [shape=box, style=filled, color=grey]; - "376E" [shape=box, style=filled, color=grey]; - "384E" [label=aeb8, shape=box, style=filled, color=grey]; - "386E" [label="2e53009d4a375", shape=box, style=filled, color=grey]; - "428E" [shape=box, style=filled, color=grey]; - "474E" [shape=box, style=filled, color=grey]; - "484E" [shape=box, style=filled, color=grey]; - "546E" [label=dea1d1, shape=box, style=filled, color=grey]; - "548E" [label="5a0b4b906a", shape=box, style=filled, color=grey]; - 314 [label="1727041c622518c9dd24f7c211", shape=hexagon]; - "113E" [label="49704867bee95", shape=box, style=filled, color=grey]; - 315 [label="31f2f9aef958979f9f3532b9b", shape=hexagon, style=filled, color="#ff0000"]; - "43E" [label="47cd70f", shape=box, style=filled, color=grey]; - "240E" [label="248df40dae", shape=box, style=filled, color=grey]; - "298E" [shape=box, style=filled, color=grey]; - "334E" [label="9dd5bf47f", shape=box, style=filled, color=grey]; - "360E" [shape=box, style=filled, color=grey]; - "390E" [label="28533c", shape=box, style=filled, color=grey]; - "418E" [shape=box, style=filled, color=grey]; - "492E" [label=a4c7d0, shape=box, style=filled, color=grey]; - "502E" [label="4f6f7f", shape=box, style=filled, color=grey]; - "584E" [label="7ab64a969", shape=box, style=filled, color=grey]; - "588E" [shape=box, style=filled, color=grey]; - "602E" [label=69, shape=box, style=filled, color=grey]; - "606E" [label="67513d", shape=box, style=filled, color=grey]; - "662E" [label=cf, shape=box, style=filled, color=grey]; - 316 [label=a54092a3033f7d5e41e0a76c1, shape=hexagon]; - "51E" [label="1467f017b74e", shape=box, style=filled, color=grey]; - 317 [label="2043b477ac0393676a4309514d0", shape=hexagon]; - "116E" [label=bdec8c86db51b9, shape=box, style=filled, color=grey]; - 318 [label=ab48d1f65812bc0f8ab6941c3b5, shape=hexagon]; - "74E" [label=81, shape=box, style=filled, color=grey]; - 319 [label=ca3d67754cf62fdafbf0a1e0, shape=hexagon]; - "57E" [label="75b14f1719d", shape=box, style=filled, color=grey]; - "94E" [label="62f36ea98a", shape=box, style=filled, color=grey]; - "350E" [label=e3a76d31ca59a, shape=box, style=filled, color=grey]; - "440E" [label=b3cadc253f7, shape=box, style=filled, color=grey]; - "466E" [label=fb58e11, shape=box, style=filled, color=grey]; - "676E" [label="8606837526d81cdec", shape=box, style=filled, color=grey]; - 320 [label=a7a7f3681dad1250b01cf80bc17, shape=hexagon]; - "60E" [label="2c514b0cd8f7d3", shape=box, style=filled, color=grey]; - "366E" [label="7e494b", shape=box, style=filled, color=grey]; - "434E" [label="15d44ab97", shape=box, style=filled, color=grey]; - "458E" [label="78b2d75d00166", shape=box, style=filled, color=grey]; - "618E" [label="761e0f72f95", shape=box, style=filled, color=grey]; - 321 [label="275afb2b215b966d9fac51b96b9", shape=hexagon]; - "72E" [label=ac284d73563, shape=box, style=filled, color=grey]; - "362E" [label="7e74e1587f3a4d208", shape=box, style=filled, color=grey]; - "372E" [label=ffd1b1af3b6864078f3, shape=box, style=filled, color=grey]; - "572E" [label=b38049e00, shape=box, style=filled, color=grey]; - 322 [label=c3c93c700edc0cb4f95f03c04, shape=hexagon]; - "54E" [label="99237fce1358", shape=box, style=filled, color=grey]; - "222E" [label="3dcf8f454", shape=box, style=filled, color=grey]; - "302E" [label=c5acd20cad2, shape=box, style=filled, color=grey]; - "556E" [label="6c998bf2a5edd", shape=box, style=filled, color=grey]; - "558E" [label="4b683", shape=box, style=filled, color=grey]; - 323 [label="63a3d4fb9d38a0182be6e39e76", shape=hexagon]; - "37E" [label=bba6e6e194ccf, shape=box, style=filled, color=grey]; - "208E" [label=01938827, shape=box, style=filled, color=grey]; - "210E" [label=9, shape=box, style=filled, color=grey]; - "352E" [label="64ef1d545", shape=box, style=filled, color=grey]; - "450E" [label=b473716, shape=box, style=filled, color=grey]; - "568E" [label="7c13bf753da", shape=box, style=filled, color=grey]; - "576E" [label="4e4a79111d", shape=box, style=filled, color=grey]; - "686E" [label=af4abb0d6a99, shape=box, style=filled, color=grey]; - 324 [label="4399cf78123dedd0dfe9776104", shape=hexagon]; - "228E" [label=af9c489df53, shape=box, style=filled, color=grey]; - "248E" [label="3703059dbc5a8", shape=box, style=filled, color=grey]; - "304E" [label="8a46e6", shape=box, style=filled, color=grey]; - "468E" [label=f9d09, shape=box, style=filled, color=grey]; - "578E" [label=cd1e9af3dec2, shape=box, style=filled, color=grey]; - "660E" [label="9e650e89bb", shape=box, style=filled, color=grey]; - "688E" [label=f62b136b2171, shape=box, style=filled, color=grey]; - "694E" [label="4727c415d06bcbef", shape=box, style=filled, color=grey]; - "714E" [label="38b3b0d9", shape=box, style=filled, color=grey]; - "766E" [label=a153512d982, shape=box, style=filled, color=grey]; - 325 [label="40f253cd228f7ac2d0aee", shape=hexagon]; - "97E" [label=a3ff993, shape=box, style=filled, color=grey]; - "506E" [label="7528dd86b", shape=box, style=filled, color=grey]; - 326 [label="89a2505da6179a80202d4a6c3", shape=hexagon]; - "61E" [label="75eea05672a5", shape=box, style=filled, color=grey]; - "175E" [label="3b0c08dd2ca", shape=box, style=filled, color=grey]; - "482E" [label=a3781072b, shape=box, style=filled, color=grey]; - 328 [label="2601085bde1b2450d64509f36", shape=hexagon]; - "75E" [label="0efbd", shape=box, style=filled, color=grey]; - "580E" [label=bb92d1da1f38d52f8ff, shape=box, style=filled, color=grey]; - 329 [label="5c81103c751345d0ee0f4bd", shape=hexagon]; - "96E" [label=b23526044, shape=box, style=filled, color=grey]; - 330 [label=fcbd9ad14139718bc6fcc8b4, shape=hexagon]; - "100E" [label="73ca543bf1", shape=box, style=filled, color=grey]; - "170E" [label=c2f32e2cf9, shape=box, style=filled, color=grey]; - 333 [label="44cbb41a9cfc15497eacd294", shape=doubleoctagon, style=filled, color=yellow]; - "63E" [label="6a91", shape=box, style=filled, color=grey]; - "67E" [label=b074e, shape=box, style=filled, color=grey]; - "68E" [label=06209, shape=box, style=filled, color=grey]; - "69E" [label="58e3dcc618", shape=box, style=filled, color=grey]; - "70E" [label=eee44624da, shape=box, style=filled, color=grey]; - "71E" [label="6a91", shape=box, style=filled, color=grey]; - "802E" [label=e1e8c, shape=box, style=filled, color=grey]; - "793E" [shape=box, style=filled, color=grey]; - 334 [label=b46b0756dba915943839e90a55, shape=doubleoctagon, style=filled, color=yellow]; - "64E" [label="5fdf", shape=box, style=filled, color=grey]; - "81E" [label="3eca1f94dc181", shape=box, style=filled, color=grey]; - "82E" [label="6b1bb9b0e", shape=box, style=filled, color=grey]; - "83E" [label=a54d477232, shape=box, style=filled, color=grey]; - "84E" [label=a164d9f60fbbdd, shape=box, style=filled, color=grey]; - "85E" [label="78c8463ea", shape=box, style=filled, color=grey]; - "86E" [label=c110ba7, shape=box, style=filled, color=grey]; - "87E" [label="3b63cdc0f", shape=box, style=filled, color=grey]; - "88E" [label="6f578c5128", shape=box, style=filled, color=grey]; - "89E" [label="3e048573fd", shape=box, style=filled, color=grey]; - 336 [label="825c7994d5da13afe519861818", shape=tripleoctagon, style=filled, color="#ff0000", URL="tes hi", area=test]; - "1E" [label=f4bef37b6a94bfd00, shape=box, style=filled, color=grey]; - "2E" [label=d2647f8b6d8661d08, shape=box, style=filled, color=grey]; - "3E" [label="964cb56d8f69ff058", shape=box, style=filled, color=grey]; - "4E" [label="4f35e206816c3bd22", shape=box, style=filled, color=grey]; - "5E" [label=affb2d716803a2d3e, shape=box, style=filled, color=grey]; - "6E" [label=e4ae306d9bd669c70, shape=box, style=filled, color=grey]; - "7E" [label="4dbf4395236fb03ed", shape=box, style=filled, color=grey]; - "8E" [label="15b3ad672cd2f713a", shape=box, style=filled, color=grey]; - "9E" [label="8d6e6e0cd9b842a47", shape=box, style=filled, color=grey]; - "10E" [label="00d0dd018fe879f96", shape=box, style=filled, color=grey]; - "11E" [label=f28b78d4803c, shape=box, style=filled, color=grey]; - "12E" [label="2d886da042b5384b4", shape=box, style=filled, color=grey]; - "13E" [label="548c0081a62132b44", shape=box, style=filled, color=grey]; - "14E" [label="52126553e52385d16", shape=box, style=filled, color=grey]; - "15E" [label="9fe716e738eaea34e", shape=box, style=filled, color=grey]; - "16E" [label="5782807b5f575e0a8", shape=box, style=filled, color=grey]; - "17E" [label="792fd6f9df1fa1e33", shape=box, style=filled, color=grey]; - "18E" [label=c471b6fdbfb852661, shape=box, style=filled, color=grey]; - "19E" [label=a84844dfd0052b3b5, shape=box, style=filled, color=grey]; - "20E" [label="724dabdce9744d061", shape=box, style=filled, color=grey]; - "21E" [label="57f7fd2eecec93c8b", shape=box, style=filled, color=grey]; - "22E" [label=baba65f670ee34a88, shape=box, style=filled, color=grey]; - "23E" [label=ac34ec0f0488b17ec, shape=box, style=filled, color=grey]; - "24E" [label="51e74bec5513083bb", shape=box, style=filled, color=grey]; - "25E" [label="8e2d970b2f820ee35", shape=box, style=filled, color=grey]; - "26E" [label="19398d3cd6b9c674f", shape=box, style=filled, color=grey]; - "27E" [label="6505e29f4a11d9530", shape=box, style=filled, color=grey]; - "28E" [label=bc4824f07a9d2bba6, shape=box, style=filled, color=grey]; - "29E" [label="3acbf8a1537e4e1a1", shape=box, style=filled, color=grey]; - "30E" [label="536264e787cf70469", shape=box, style=filled, color=grey]; - "31E" [label=d, shape=box, style=filled, color=grey]; - "65E" [label=d4b2, shape=box, style=filled, color=grey]; - "119E" [label="2a9caef7", shape=box, style=filled, color=grey]; - "150E" [label="73d12", shape=box, style=filled, color=grey]; - "176E" [label="8896166adc0", shape=box, style=filled, color=grey]; - "743E" [label="9f", shape=box, style=filled, color=grey]; - "744E" [label="2e1313c", shape=box, style=filled, color=grey]; - "764E" [label=cd6, shape=box, style=filled, color=grey]; - 337 [label="8304a439f91fc90b3fe8dd35be8", shape=doubleoctagon, style=filled, color=yellow]; - "120E" [label="345d26b3f821fe", shape=box, style=filled, color=grey]; - "121E" [label="357679fea1e2f", shape=box, style=filled, color=grey]; - "122E" [label=c71043819b6a79, shape=box, style=filled, color=grey]; - "123E" [label=f9df653b86fb8df, shape=box, style=filled, color=grey]; - "124E" [label="020df871874cd", shape=box, style=filled, color=grey]; - "125E" [label="4c52fdd8e396692", shape=box, style=filled, color=grey]; - "126E" [label="8b98c3ddbe0b336", shape=box, style=filled, color=grey]; - "127E" [label=d9f4abac731a9e, shape=box, style=filled, color=grey]; - "128E" [label="50f4d9b97aefe", shape=box, style=filled, color=grey]; - "129E" [label=ea920d9f5b295119, shape=box, style=filled, color=grey]; - "130E" [label=ff5c9b242337c, shape=box, style=filled, color=grey]; - "131E" [label="4e12f7ff0918", shape=box, style=filled, color=grey]; - "132E" [label=ee3b6be71d59b, shape=box, style=filled, color=grey]; - "133E" [label="615cd6b5e3d21c", shape=box, style=filled, color=grey]; - "134E" [label="6d52dd1b198bb", shape=box, style=filled, color=grey]; - "135E" [label="8c932e1e502dca", shape=box, style=filled, color=grey]; - "136E" [label=e84330eef281284a, shape=box, style=filled, color=grey]; - "137E" [label="85fc23f1c88b4", shape=box, style=filled, color=grey]; - "138E" [label="5997cb0c083422", shape=box, style=filled, color=grey]; - 339 [label=b1ffbabb24d71f67d1e0ce23c51, shape=doubleoctagon, style=filled, color=yellow]; - "151E" [shape=box, style=filled, color=grey]; - "153E" [label="41a8b095c7fd3", shape=box, style=filled, color=grey]; - "154E" [label="151bcc2a8de7ea634", shape=box, style=filled, color=grey]; - "155E" [label="6c541cad8de1b15", shape=box, style=filled, color=grey]; - "156E" [label=c935c7f4d1090ac, shape=box, style=filled, color=grey]; - "157E" [label="5ce1fcfb042b", shape=box, style=filled, color=grey]; - "158E" [label=531806429433, shape=box, style=filled, color=grey]; - "159E" [label=d285240b89cb, shape=box, style=filled, color=grey]; - "160E" [label=f22c27c0f0a54e, shape=box, style=filled, color=grey]; - "161E" [label="8d0d8314d211d80", shape=box, style=filled, color=grey]; - "162E" [shape=box, style=filled, color=grey]; - 347 [label="9652ab8b55fdb2a36d1f3fe020", shape=hexagon]; - "139E" [label=ef8b68bb5772f3, shape=box, style=filled, color=grey]; - "795E" [label="16c3ae29c0bc713", shape=box, style=filled, color=grey]; - 348 [label="676bbe7d1c1fb71742df534ce8", shape=hexagon]; - "799E" [label=a78eb40ae56aaa9, shape=box, style=filled, color=grey]; - "800E" [label="6aae8d25951", shape=box, style=filled, color=grey]; - 349 [label="66c0220688a999aaf7f1702d1", shape=hexagon]; - "141E" [label="67b6a4dca3a6d", shape=box, style=filled, color=grey]; - 350 [label="1322fb0818783e6f9a4f173d47c52", shape=hexagon]; - "142E" [label="9696c0950295d8cb5", shape=box, style=filled, color=grey]; - "678E" [label=b5c747cc9, shape=box, style=filled, color=grey]; - 351 [label=ff07977fca5513098d220d1eb3a, shape=hexagon]; - "143E" [label="89a36b13f8c344b", shape=box, style=filled, color=grey]; - "232E" [label="56292d076643", shape=box, style=filled, color=grey]; - "680E" [label=b5c747cc9, shape=box, style=filled, color=grey]; - "704E" [label="431430c49", shape=box, style=filled, color=grey]; - 352 [label=a97ef281eafc34b1630d450a1df, shape=hexagon]; - "144E" [label="4ff4e275c710c3b", shape=box, style=filled, color=grey]; - "432E" [label=d13da6273c9b4da, shape=box, style=filled, color=grey]; - 353 [label="72cbb37db85ed3c6eda5dcf8", shape=hexagon]; - "145E" [label="33ff9e43d5ab", shape=box, style=filled, color=grey]; - 354 [label="0f6784e49852c0be0da23b16", shape=hexagon]; - "146E" [label=d4f958b03a98, shape=box, style=filled, color=grey]; - "396E" [label="8e24e9b4e", shape=box, style=filled, color=grey]; - 355 [label="383f5c65cc6c25aa0a0e6dbb", shape=hexagon]; - "147E" [label="1ff8ff951ee9", shape=box, style=filled, color=grey]; - 356 [label=f52a45620969f0df4e6ae1dcd7, shape=hexagon]; - "148E" [label="5256925081c812", shape=box, style=filled, color=grey]; - 357 [label="1f5df34ad75a55a76ef4afa0a47", shape=hexagon]; - "149E" [label="26a185dde9a93dd", shape=box, style=filled, color=grey]; - 358 [label="45ba4d4c61c9601a26d59e47e0260", shape=hexagon]; - "167E" [label="99bd3e7feeb710", shape=box, style=filled, color=grey]; - 359 [label=f95344b0ae31693f3a2746597d4, shape=hexagon]; - "169E" [label="4e8259973f1f", shape=box, style=filled, color=grey]; - 360 [label=b79798b186d6b82288e8be4017d, shape=hexagon]; - "171E" [label="63b079bd5847", shape=box, style=filled, color=grey]; - 361 [label="47e0067f4d853afd2012f04daa8", shape=hexagon]; - "172E" [label="92fb5d4a0805", shape=box, style=filled, color=grey]; - 362 [label=f2b6201774de40a29b504b1f716, shape=hexagon]; - "173E" [label=d7203571944b, shape=box, style=filled, color=grey]; - 363 [label="800422ab81d804eef3e7b91dfba91", shape=hexagon]; - "174E" [label="952316a1a5a785", shape=box, style=filled, color=grey]; - 364 [label="35b941379e1af658078cffb83a2", shape=hexagon]; - "101E" [label="331675c046693f", shape=box, style=filled, color=grey]; - 365 [label=d4f7b7fba7afcf7a72397353ec, shape=hexagon]; - "102E" [label="32c4684b55361", shape=box, style=filled, color=grey]; - 367 [label=e4b45b7a2f884d3734bfd5985656, shape=hexagon]; - "104E" [label="1333074979f2d0b", shape=box, style=filled, color=grey]; - 368 [label="02c2ba83680ab57f236a33d702", shape=hexagon]; - "105E" [label="084d4bfa5853e", shape=box, style=filled, color=grey]; - 369 [label="9ccd974150a18260b207b6584caa", shape=hexagon]; - "106E" [label="28f7bfc40c88e6a", shape=box, style=filled, color=grey]; - 374 [label="653ae44d45dcadeb481b53027d", shape=hexagon]; - "111E" [label="8f95518f48528", shape=box, style=filled, color=grey]; - 375 [label=d66f542ef1ce4d02c59bec65e, shape=hexagon]; - "112E" [label="2ef209509e2a", shape=box, style=filled, color=grey]; - 377 [label=a2984b7a11e49440420058c1d80, shape=hexagon]; - "114E" [label=ef42184297591d, shape=box, style=filled, color=grey]; - 378 [label="31055116421c96b37f72a262bb", shape=hexagon]; - "115E" [label=be9c5958196ed, shape=box, style=filled, color=grey]; - 380 [label="8462bb2eec1a62d19a15865e57c92", shape=hexagon]; - "117E" [label="16a795a1d63f30df", shape=box, style=filled, color=grey]; - "392E" [label="85a34bc9616ff", shape=box, style=filled, color=grey]; - 381 [label=c21eb96fe100a1efaa128181b7, shape=hexagon]; - "118E" [label=f1b0d754353a6, shape=box, style=filled, color=grey]; - 382 [label=e3e284d0cc803d98d674f9c3f6d, shape=doubleoctagon, style=filled, color=yellow]; - "177E" [label="30417faf916", shape=box, style=filled, color=grey]; - "178E" [label=e618df70814a, shape=box, style=filled, color=grey]; - "179E" [label=fa90ddf10bd574, shape=box, style=filled, color=grey]; - "180E" [label="815cc0b83d733", shape=box, style=filled, color=grey]; - "181E" [label=f787d827958c, shape=box, style=filled, color=grey]; - "182E" [label=f20f7f513e, shape=box, style=filled, color=grey]; - "183E" [label="290907417e13", shape=box, style=filled, color=grey]; - "184E" [label=e8386a8e1c8a, shape=box, style=filled, color=grey]; - "185E" [label="319bc900218b", shape=box, style=filled, color=grey]; - "186E" [label="3ba7afb0e48ae1", shape=box, style=filled, color=grey]; - "187E" [label="6ba0776fc8e", shape=box, style=filled, color=grey]; - "188E" [label="09847696ae", shape=box, style=filled, color=grey]; - 383 [label="908f9ad506eae9ab6ada185e3", shape=doubleoctagon, style=filled, color=yellow]; - "730E" [label="65694ca6d575", shape=box, style=filled, color=grey]; - "732E" [label="37f57e81ebed95", shape=box, style=filled, color=grey]; - "741E" [label="9b6c", shape=box, style=filled, color=grey]; - "765E" [label="88ebe2e8782c", shape=box, style=filled, color=grey]; - "796E" [label="901b2105a902ee7791", shape=box, style=filled, color=grey]; - 384 [label="593caebf2037317648bb451aa79", shape=doubleoctagon, style=filled, color=yellow]; - "726E" [label="351dd0aefe480c", shape=box, style=filled, color=grey]; - "728E" [label="56e1a896", shape=box, style=filled, color=grey]; - "742E" [label="5ba4693031", shape=box, style=filled, color=grey]; - 1 -> "189E" [label=" ", color=blue, arrowhead=dot]; - 1 -> "790E" [label=" ", color=blue, arrowhead=dot]; - 2 -> "191E" [label=" ", color=blue, arrowhead=dot]; - 3 -> "193E" [label=" ", color=blue, arrowhead=dot]; - 4 -> "195E" [label=" ", color=blue, arrowhead=dot]; - 5 -> "197E" [label=" ", color=blue, arrowhead=dot]; - 6 -> "199E" [label=" ", color=blue, arrowhead=dot]; - 7 -> "201E" [label=" ", color=blue, arrowhead=dot]; - 8 -> "203E" [label=" ", color=blue, arrowhead=dot]; - 9 -> "725E" [label=" ", color=blue, arrowhead=dot]; - 9 -> "785E" [label=" ", color=blue, arrowhead=dot]; - 10 -> "205E" [label=" ", color=blue, arrowhead=dot]; - 11 -> "207E" [label=" ", color=blue, arrowhead=dot]; - 12 -> "209E" [label=" ", color=blue, arrowhead=dot]; - 13 -> "211E" [label=" ", color=blue, arrowhead=dot]; - 14 -> "213E" [label=" ", color=blue, arrowhead=dot]; - 15 -> "215E" [label=" ", color=blue, arrowhead=dot]; - 16 -> "727E" [label=" ", color=blue, arrowhead=dot]; - 16 -> "784E" [label=" ", color=blue, arrowhead=dot]; - 17 -> "217E" [label=" ", color=blue, arrowhead=dot]; - 17 -> "787E" [label=" ", color=blue, arrowhead=dot]; - 18 -> "219E" [label=" ", color=blue, arrowhead=dot]; - 19 -> "221E" [label=" ", color=blue, arrowhead=dot]; - 20 -> "223E" [label=" ", color=blue, arrowhead=dot]; - 21 -> "225E" [label=" ", color=blue, arrowhead=dot]; - 22 -> "227E" [label=" ", color=blue, arrowhead=dot]; - 22 -> "792E" [label=" ", color=blue, arrowhead=dot]; - 23 -> "231E" [label=" ", color=blue, arrowhead=dot]; - 24 -> "233E" [label=" ", color=blue, arrowhead=dot]; - 25 -> "235E" [label=" ", color=blue, arrowhead=dot]; - 26 -> "237E" [label=" ", color=blue, arrowhead=dot]; - 27 -> "239E" [label=" ", color=blue, arrowhead=dot]; - 27 -> "783E" [label=" ", color=blue, arrowhead=dot]; - 28 -> "241E" [label=" ", color=blue, arrowhead=dot]; - 28 -> "791E" [label=" ", color=blue, arrowhead=dot]; - 29 -> "243E" [label=" ", color=blue, arrowhead=dot]; - 30 -> "245E" [label=" ", color=blue, arrowhead=dot]; - 31 -> "247E" [label=" ", color=blue, arrowhead=dot]; - 32 -> "249E" [label=" ", color=blue, arrowhead=dot]; - 33 -> "251E" [label=" ", color=blue, arrowhead=dot]; - 34 -> "253E" [label=" ", color=blue, arrowhead=dot]; - 35 -> "255E" [label=" ", color=blue, arrowhead=dot]; - 36 -> "257E" [label=" ", color=blue, arrowhead=dot]; - 37 -> "259E" [label=" ", color=blue, arrowhead=dot]; - 38 -> "261E" [label=" ", color=blue, arrowhead=dot]; - 39 -> "263E" [label=" ", color=blue, arrowhead=dot]; - 40 -> "265E" [label=" ", color=blue, arrowhead=dot]; - 41 -> "267E" [label=" ", color=blue, arrowhead=dot]; - 42 -> "269E" [label=" ", color=blue, arrowhead=dot]; - 43 -> "271E" [label=" ", color=blue, arrowhead=dot]; - 44 -> "273E" [label=" ", color=blue, arrowhead=dot]; - 45 -> "275E" [label=" ", color=blue, arrowhead=dot]; - 46 -> "277E" [label=" ", color=blue, arrowhead=dot]; - 47 -> "279E" [label=" ", color=blue, arrowhead=dot]; - 48 -> "281E" [label=" ", color=blue, arrowhead=dot]; - 49 -> "283E" [label=" ", color=blue, arrowhead=dot]; - 50 -> "285E" [label=" ", color=blue, arrowhead=dot]; - 51 -> "287E" [label=" ", color=blue, arrowhead=dot]; - 52 -> "289E" [label=" ", color=blue, arrowhead=dot]; - 53 -> "291E" [label=" ", color=blue, arrowhead=dot]; - 54 -> "293E" [label=" ", color=blue, arrowhead=dot]; - 56 -> "295E" [label=" ", color=blue, arrowhead=dot]; - 57 -> "297E" [label=" ", color=blue, arrowhead=dot]; - 58 -> "299E" [label=" ", color=blue, arrowhead=dot]; - 59 -> "301E" [label=" ", color=blue, arrowhead=dot]; - 59 -> "789E" [label=" ", color=blue, arrowhead=dot]; - 60 -> "303E" [label=" ", color=blue, arrowhead=dot]; - 61 -> "305E" [label=" ", color=blue, arrowhead=dot]; - 62 -> "307E" [label=" ", color=blue, arrowhead=dot]; - 63 -> "309E" [label=" ", color=blue, arrowhead=dot]; - 64 -> "311E" [label=" ", color=blue, arrowhead=dot]; - 65 -> "313E" [label=" ", color=blue, arrowhead=dot]; - 66 -> "315E" [label=" ", color=blue, arrowhead=dot]; - 67 -> "317E" [label=" ", color=blue, arrowhead=dot]; - 68 -> "319E" [label=" ", color=blue, arrowhead=dot]; - 70 -> "321E" [label=" ", color=blue, arrowhead=dot]; - 71 -> "327E" [label=" ", color=blue, arrowhead=dot]; - 72 -> "329E" [label=" ", color=blue, arrowhead=dot]; - 73 -> "331E" [label=" ", color=blue, arrowhead=dot]; - 74 -> "333E" [label=" ", color=blue, arrowhead=dot]; - 75 -> "335E" [label=" ", color=blue, arrowhead=dot]; - 76 -> "337E" [label=" ", color=blue, arrowhead=dot]; - 77 -> "339E" [label=" ", color=blue, arrowhead=dot]; - 78 -> "341E" [label=" ", color=blue, arrowhead=dot]; - 79 -> "343E" [label=" ", color=blue, arrowhead=dot]; - 80 -> "345E" [label=" ", color=blue, arrowhead=dot]; - 81 -> "347E" [label=" ", color=blue, arrowhead=dot]; - 82 -> "349E" [label=" ", color=blue, arrowhead=dot]; - 83 -> "351E" [label=" ", color=blue, arrowhead=dot]; - 84 -> "353E" [label=" ", color=blue, arrowhead=dot]; - 85 -> "355E" [label=" ", color=blue, arrowhead=dot]; - 85 -> "788E" [label=" ", color=blue, arrowhead=dot]; - 86 -> "357E" [label=" ", color=blue, arrowhead=dot]; - 87 -> "359E" [label=" ", color=blue, arrowhead=dot]; - 88 -> "361E" [label=" ", color=blue, arrowhead=dot]; - 89 -> "363E" [label=" ", color=blue, arrowhead=dot]; - 90 -> "365E" [label=" ", color=blue, arrowhead=dot]; - 91 -> "367E" [label=" ", color=blue, arrowhead=dot]; - 92 -> "369E" [label=" ", color=blue, arrowhead=dot]; - 93 -> "729E" [label=" ", color=blue, arrowhead=dot]; - 94 -> "371E" [label=" ", color=blue, arrowhead=dot]; - 95 -> "373E" [label=" ", color=blue, arrowhead=dot]; - 96 -> "375E" [label=" ", color=blue, arrowhead=dot]; - 98 -> "377E" [label=" ", color=blue, arrowhead=dot]; - 99 -> "379E" [label=" ", color=blue, arrowhead=dot]; - 100 -> "381E" [label=" ", color=blue, arrowhead=dot]; - 101 -> "383E" [label=" ", color=blue, arrowhead=dot]; - 102 -> "385E" [label=" ", color=blue, arrowhead=dot]; - 103 -> "387E" [label=" ", color=blue, arrowhead=dot]; - 104 -> "389E" [label=" ", color=blue, arrowhead=dot]; - 105 -> "391E" [label=" ", color=blue, arrowhead=dot]; - 106 -> "393E" [label=" ", color=blue, arrowhead=dot]; - 107 -> "395E" [label=" ", color=blue, arrowhead=dot]; - 108 -> "397E" [label=" ", color=blue, arrowhead=dot]; - 109 -> "399E" [label=" ", color=blue, arrowhead=dot]; - 110 -> "401E" [label=" ", color=blue, arrowhead=dot]; - 111 -> "403E" [label=" ", color=blue, arrowhead=dot]; - 112 -> "405E" [label=" ", color=blue, arrowhead=dot]; - 113 -> "407E" [label=" ", color=blue, arrowhead=dot]; - 114 -> "409E" [label=" ", color=blue, arrowhead=dot]; - 115 -> "411E" [label=" ", color=blue, arrowhead=dot]; - 116 -> "413E" [label=" ", color=blue, arrowhead=dot]; - 117 -> "415E" [label=" ", color=blue, arrowhead=dot]; - 118 -> "417E" [label=" ", color=blue, arrowhead=dot]; - 119 -> "419E" [label=" ", color=blue, arrowhead=dot]; - 120 -> "421E" [label=" ", color=blue, arrowhead=dot]; - 121 -> "423E" [label=" ", color=blue, arrowhead=dot]; - 123 -> "425E" [label=" ", color=blue, arrowhead=dot]; - 124 -> "427E" [label=" ", color=blue, arrowhead=dot]; - 124 -> "786E" [label=" ", color=blue, arrowhead=dot]; - 125 -> "431E" [label=" ", color=blue, arrowhead=dot]; - 126 -> "433E" [label=" ", color=blue, arrowhead=dot]; - 127 -> "435E" [label=" ", color=blue, arrowhead=dot]; - 128 -> "437E" [label=" ", color=blue, arrowhead=dot]; - 129 -> "439E" [label=" ", color=blue, arrowhead=dot]; - 130 -> "441E" [label=" ", color=blue, arrowhead=dot]; - 131 -> "443E" [label=" ", color=blue, arrowhead=dot]; - 132 -> "445E" [label=" ", color=blue, arrowhead=dot]; - 134 -> "447E" [label=" ", color=blue, arrowhead=dot]; - 135 -> "449E" [label=" ", color=blue, arrowhead=dot]; - 135 -> "769E" [label=" ", color=blue, arrowhead=dot]; - 135 -> "770E" [label=" ", color=blue, arrowhead=dot]; - 136 -> "451E" [label=" ", color=blue, arrowhead=dot]; - 137 -> "453E" [label=" ", color=blue, arrowhead=dot]; - 138 -> "455E" [label=" ", color=blue, arrowhead=dot]; - 139 -> "457E" [label=" ", color=blue, arrowhead=dot]; - 140 -> "459E" [label=" ", color=blue, arrowhead=dot]; - 141 -> "461E" [label=" ", color=blue, arrowhead=dot]; - 142 -> "463E" [label=" ", color=blue, arrowhead=dot]; - 143 -> "465E" [label=" ", color=blue, arrowhead=dot]; - 144 -> "467E" [label=" ", color=blue, arrowhead=dot]; - 145 -> "469E" [label=" ", color=blue, arrowhead=dot]; - 146 -> "471E" [label=" ", color=blue, arrowhead=dot]; - 147 -> "473E" [label=" ", color=blue, arrowhead=dot]; - 148 -> "475E" [label=" ", color=blue, arrowhead=dot]; - 149 -> "477E" [label=" ", color=blue, arrowhead=dot]; - 150 -> "479E" [label=" ", color=blue, arrowhead=dot]; - 151 -> "481E" [label=" ", color=blue, arrowhead=dot]; - 152 -> "483E" [label=" ", color=blue, arrowhead=dot]; - 153 -> "731E" [label=" ", color=blue, arrowhead=dot]; - 155 -> "485E" [label=" ", color=blue, arrowhead=dot]; - 156 -> "487E" [label=" ", color=blue, arrowhead=dot]; - 157 -> "489E" [label=" ", color=blue, arrowhead=dot]; - 158 -> "491E" [label=" ", color=blue, arrowhead=dot]; - 159 -> "495E" [label=" ", color=blue, arrowhead=dot]; - 160 -> "499E" [label=" ", color=blue, arrowhead=dot]; - 161 -> "501E" [label=" ", color=blue, arrowhead=dot]; - 162 -> "503E" [label=" ", color=blue, arrowhead=dot]; - 163 -> "505E" [label=" ", color=blue, arrowhead=dot]; - 164 -> "507E" [label=" ", color=blue, arrowhead=dot]; - 165 -> "509E" [label=" ", color=blue, arrowhead=dot]; - 166 -> "511E" [label=" ", color=blue, arrowhead=dot]; - 167 -> "513E" [label=" ", color=blue, arrowhead=dot]; - 168 -> "515E" [label=" ", color=blue, arrowhead=dot]; - 169 -> "517E" [label=" ", color=blue, arrowhead=dot]; - 170 -> "519E" [label=" ", color=blue, arrowhead=dot]; - 171 -> "521E" [label=" ", color=blue, arrowhead=dot]; - 172 -> "523E" [label=" ", color=blue, arrowhead=dot]; - 173 -> "525E" [label=" ", color=blue, arrowhead=dot]; - 174 -> "527E" [label=" ", color=blue, arrowhead=dot]; - 175 -> "529E" [label=" ", color=blue, arrowhead=dot]; - 176 -> "531E" [label=" ", color=blue, arrowhead=dot]; - 177 -> "533E" [label=" ", color=blue, arrowhead=dot]; - 178 -> "535E" [label=" ", color=blue, arrowhead=dot]; - 179 -> "537E" [label=" ", color=blue, arrowhead=dot]; - 180 -> "539E" [label=" ", color=blue, arrowhead=dot]; - 181 -> "541E" [label=" ", color=blue, arrowhead=dot]; - 182 -> "543E" [label=" ", color=blue, arrowhead=dot]; - 183 -> "545E" [label=" ", color=blue, arrowhead=dot]; - 184 -> "547E" [label=" ", color=blue, arrowhead=dot]; - 185 -> "549E" [label=" ", color=blue, arrowhead=dot]; - 186 -> "551E" [label=" ", color=blue, arrowhead=dot]; - 187 -> "553E" [label=" ", color=blue, arrowhead=dot]; - 188 -> "555E" [label=" ", color=blue, arrowhead=dot]; - 189 -> "557E" [label=" ", color=blue, arrowhead=dot]; - 190 -> "559E" [label=" ", color=blue, arrowhead=dot]; - 191 -> "561E" [label=" ", color=blue, arrowhead=dot]; - 192 -> "563E" [label=" ", color=blue, arrowhead=dot]; - 193 -> "565E" [label=" ", color=blue, arrowhead=dot]; - 194 -> "567E" [label=" ", color=blue, arrowhead=dot]; - 195 -> "569E" [label=" ", color=blue, arrowhead=dot]; - 196 -> "571E" [label=" ", color=blue, arrowhead=dot]; - 197 -> "573E" [label=" ", color=blue, arrowhead=dot]; - 198 -> "575E" [label=" ", color=blue, arrowhead=dot]; - 199 -> "577E" [label=" ", color=blue, arrowhead=dot]; - 200 -> "579E" [label=" ", color=blue, arrowhead=dot]; - 201 -> "581E" [label=" ", color=blue, arrowhead=dot]; - 202 -> "583E" [label=" ", color=blue, arrowhead=dot]; - 203 -> "585E" [label=" ", color=blue, arrowhead=dot]; - 204 -> "587E" [label=" ", color=blue, arrowhead=dot]; - 206 -> "589E" [label=" ", color=blue, arrowhead=dot]; - 208 -> "597E" [label=" ", color=blue, arrowhead=dot]; - 209 -> "599E" [label=" ", color=blue, arrowhead=dot]; - 210 -> "601E" [label=" ", color=blue, arrowhead=dot]; - 211 -> "603E" [label=" ", color=blue, arrowhead=dot]; - 212 -> "605E" [label=" ", color=blue, arrowhead=dot]; - 213 -> "607E" [label=" ", color=blue, arrowhead=dot]; - 214 -> "609E" [label=" ", color=blue, arrowhead=dot]; - 215 -> "611E" [label=" ", color=blue, arrowhead=dot]; - 216 -> "613E" [label=" ", color=blue, arrowhead=dot]; - 217 -> "615E" [label=" ", color=blue, arrowhead=dot]; - 218 -> "617E" [label=" ", color=blue, arrowhead=dot]; - 219 -> "619E" [label=" ", color=blue, arrowhead=dot]; - 221 -> "623E" [label=" ", color=blue, arrowhead=dot]; - 223 -> "625E" [label=" ", color=blue, arrowhead=dot]; - 224 -> "627E" [label=" ", color=blue, arrowhead=dot]; - 225 -> "629E" [label=" ", color=blue, arrowhead=dot]; - 226 -> "631E" [label=" ", color=blue, arrowhead=dot]; - 227 -> "633E" [label=" ", color=blue, arrowhead=dot]; - 228 -> "635E" [label=" ", color=blue, arrowhead=dot]; - 229 -> "637E" [label=" ", color=blue, arrowhead=dot]; - 230 -> "639E" [label=" ", color=blue, arrowhead=dot]; - 231 -> "641E" [label=" ", color=blue, arrowhead=dot]; - 232 -> "643E" [label=" ", color=blue, arrowhead=dot]; - 233 -> "645E" [label=" ", color=blue, arrowhead=dot]; - 234 -> "647E" [label=" ", color=blue, arrowhead=dot]; - 235 -> "649E" [label=" ", color=blue, arrowhead=dot]; - 236 -> "651E" [label=" ", color=blue, arrowhead=dot]; - 237 -> "653E" [label=" ", color=blue, arrowhead=dot]; - 238 -> "655E" [label=" ", color=blue, arrowhead=dot]; - 239 -> "657E" [label=" ", color=blue, arrowhead=dot]; - 240 -> "659E" [label=" ", color=blue, arrowhead=dot]; - 241 -> "661E" [label=" ", color=blue, arrowhead=dot]; - 242 -> "663E" [label=" ", color=blue, arrowhead=dot]; - 243 -> "665E" [label=" ", color=blue, arrowhead=dot]; - 244 -> "667E" [label=" ", color=blue, arrowhead=dot]; - 245 -> "669E" [label=" ", color=blue, arrowhead=dot]; - 246 -> "671E" [label=" ", color=blue, arrowhead=dot]; - 247 -> "673E" [label=" ", color=blue, arrowhead=dot]; - 248 -> "675E" [label=" ", color=blue, arrowhead=dot]; - 249 -> "679E" [label=" ", color=blue, arrowhead=dot]; - 251 -> "681E" [label=" ", color=blue, arrowhead=dot]; - 252 -> "683E" [label=" ", color=blue, arrowhead=dot]; - 253 -> "685E" [label=" ", color=blue, arrowhead=dot]; - 254 -> "687E" [label=" ", color=blue, arrowhead=dot]; - 255 -> "689E" [label=" ", color=blue, arrowhead=dot]; - 256 -> "691E" [label=" ", color=blue, arrowhead=dot]; - 257 -> "693E" [label=" ", color=blue, arrowhead=dot]; - 258 -> "695E" [label=" ", color=blue, arrowhead=dot]; - 259 -> "697E" [label=" ", color=blue, arrowhead=dot]; - 260 -> "699E" [label=" ", color=blue, arrowhead=dot]; - 261 -> "703E" [label=" ", color=blue, arrowhead=dot]; - 262 -> "705E" [label=" ", color=blue, arrowhead=dot]; - 264 -> "709E" [label=" ", color=blue, arrowhead=dot]; - 265 -> "711E" [label=" ", color=blue, arrowhead=dot]; - 266 -> "713E" [label=" ", color=blue, arrowhead=dot]; - 267 -> "715E" [label=" ", color=blue, arrowhead=dot]; - 268 -> "717E" [label=" ", color=blue, arrowhead=dot]; - 269 -> "719E" [label=" ", color=blue, arrowhead=dot]; - 270 -> "721E" [label=" ", color=blue, arrowhead=dot]; - 272 -> "34E" [label=" ", color=blue, arrowhead=dot]; - 272 -> "252E" [label=" ", color=blue, arrowhead=dot]; - 272 -> "436E" [label=" ", color=blue, arrowhead=dot]; - 274 -> "59E" [label=" ", color=blue, arrowhead=dot]; - 274 -> "500E" [label=" ", color=blue, arrowhead=dot]; - 274 -> "720E" [label=" ", color=blue, arrowhead=dot]; - 275 -> "98E" [label=" ", color=blue, arrowhead=dot]; - 278 -> "35E" [label=" ", color=blue, arrowhead=dot]; - 278 -> "488E" [label=" ", color=blue, arrowhead=dot]; - 278 -> "598E" [label=" ", color=blue, arrowhead=dot]; - 278 -> "604E" [label=" ", color=blue, arrowhead=dot]; - 278 -> "628E" [label=" ", color=blue, arrowhead=dot]; - 279 -> "99E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "242E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "270E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "272E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "284E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "286E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "288E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "586E" [label=" ", color=blue, arrowhead=dot]; - 280 -> "763E" [label=" ", color=blue, arrowhead=dot]; - 281 -> "45E" [label=" ", color=blue, arrowhead=dot]; - 281 -> "470E" [label=" ", color=blue, arrowhead=dot]; - 281 -> "670E" [label=" ", color=blue, arrowhead=dot]; - 281 -> "722E" [label=" ", color=blue, arrowhead=dot]; - 282 -> "103E" [label=" ", color=blue, arrowhead=dot]; - 283 -> "165E" [label=" ", color=blue, arrowhead=dot]; - 284 -> "39E" [label=" ", color=blue, arrowhead=dot]; - 284 -> "224E" [label=" ", color=blue, arrowhead=dot]; - 284 -> "268E" [label=" ", color=blue, arrowhead=dot]; - 284 -> "632E" [label=" ", color=blue, arrowhead=dot]; - 284 -> "710E" [label=" ", color=blue, arrowhead=dot]; - 285 -> "53E" [label=" ", color=blue, arrowhead=dot]; - 286 -> "38E" [label=" ", color=blue, arrowhead=dot]; - 286 -> "166E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "40E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "218E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "244E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "246E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "258E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "290E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "292E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "308E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "318E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "388E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "472E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "478E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "566E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "570E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "574E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "608E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "614E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "658E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "664E" [label=" ", color=blue, arrowhead=dot]; - 288 -> "682E" [label=" ", color=blue, arrowhead=dot]; - 289 -> "41E" [label=" ", color=blue, arrowhead=dot]; - 289 -> "636E" [label=" ", color=blue, arrowhead=dot]; - 289 -> "642E" [label=" ", color=blue, arrowhead=dot]; - 289 -> "690E" [label=" ", color=blue, arrowhead=dot]; - 289 -> "700E" [label=" ", color=blue, arrowhead=dot]; - 290 -> "56E" [label=" ", color=blue, arrowhead=dot]; - 290 -> "264E" [label=" ", color=blue, arrowhead=dot]; - 290 -> "510E" [label=" ", color=blue, arrowhead=dot]; - 290 -> "718E" [label=" ", color=blue, arrowhead=dot]; - 291 -> "66E" [label=" ", color=blue, arrowhead=dot]; - 291 -> "76E" [label=" ", color=blue, arrowhead=dot]; - 291 -> "610E" [label=" ", color=blue, arrowhead=dot]; - 292 -> "73E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "49E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "214E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "216E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "236E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "278E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "358E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "398E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "400E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "402E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "404E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "406E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "408E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "412E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "438E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "448E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "476E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "504E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "552E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "634E" [label=" ", color=blue, arrowhead=dot]; - 293 -> "768E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "44E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "92E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "250E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "316E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "380E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "424E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "442E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "446E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "454E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "460E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "462E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "648E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "656E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "666E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "692E" [label=" ", color=blue, arrowhead=dot]; - 295 -> "712E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "47E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "330E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "514E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "516E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "518E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "520E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "522E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "526E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "528E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "530E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "532E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "534E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "536E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "538E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "540E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "542E" [label=" ", color=blue, arrowhead=dot]; - 296 -> "544E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "46E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "93E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "206E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "426E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "550E" [label=" ", color=blue, arrowhead=dot]; - 297 -> "706E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "36E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "95E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "364E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "394E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "420E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "456E" [label=" ", color=blue, arrowhead=dot]; - 298 -> "624E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "48E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "168E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "260E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "282E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "554E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "590E" [label=" ", color=blue, arrowhead=dot]; - 299 -> "767E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "62E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "190E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "226E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "238E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "254E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "256E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "262E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "266E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "274E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "276E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "294E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "296E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "310E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "320E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "322E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "332E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "340E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "344E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "346E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "348E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "374E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "378E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "452E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "508E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "524E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "612E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "626E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "638E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "644E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "654E" [label=" ", color=blue, arrowhead=dot]; - 300 -> "672E" [label=" ", color=blue, arrowhead=dot]; - 302 -> "797E" [label=" ", color=blue, arrowhead=dot]; - 302 -> "798E" [label=" ", color=blue, arrowhead=dot]; - 303 -> "52E" [label=" ", color=blue, arrowhead=dot]; - 303 -> "650E" [label=" ", color=blue, arrowhead=dot]; - 304 -> "50E" [label=" ", color=blue, arrowhead=dot]; - 304 -> "640E" [label=" ", color=blue, arrowhead=dot]; - 304 -> "646E" [label=" ", color=blue, arrowhead=dot]; - 304 -> "652E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "55E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "220E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "338E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "368E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "486E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "490E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "562E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "564E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "600E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "668E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "674E" [label=" ", color=blue, arrowhead=dot]; - 306 -> "698E" [label=" ", color=blue, arrowhead=dot]; - 307 -> "107E" [label=" ", color=blue, arrowhead=dot]; - 308 -> "108E" [label=" ", color=blue, arrowhead=dot]; - 309 -> "109E" [label=" ", color=blue, arrowhead=dot]; - 310 -> "110E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "58E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "234E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "300E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "306E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "314E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "342E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "354E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "370E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "382E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "422E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "444E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "582E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "620E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "630E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "684E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "696E" [label=" ", color=blue, arrowhead=dot]; - 311 -> "801E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "42E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "192E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "194E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "196E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "198E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "200E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "202E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "204E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "312E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "336E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "376E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "384E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "386E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "428E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "474E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "484E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "546E" [label=" ", color=blue, arrowhead=dot]; - 312 -> "548E" [label=" ", color=blue, arrowhead=dot]; - 314 -> "113E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "43E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "240E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "298E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "334E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "360E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "390E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "418E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "492E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "502E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "584E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "588E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "602E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "606E" [label=" ", color=blue, arrowhead=dot]; - 315 -> "662E" [label=" ", color=blue, arrowhead=dot]; - 316 -> "51E" [label=" ", color=blue, arrowhead=dot]; - 317 -> "116E" [label=" ", color=blue, arrowhead=dot]; - 318 -> "74E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "57E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "94E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "350E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "440E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "466E" [label=" ", color=blue, arrowhead=dot]; - 319 -> "676E" [label=" ", color=blue, arrowhead=dot]; - 320 -> "60E" [label=" ", color=blue, arrowhead=dot]; - 320 -> "366E" [label=" ", color=blue, arrowhead=dot]; - 320 -> "434E" [label=" ", color=blue, arrowhead=dot]; - 320 -> "458E" [label=" ", color=blue, arrowhead=dot]; - 320 -> "618E" [label=" ", color=blue, arrowhead=dot]; - 321 -> "72E" [label=" ", color=blue, arrowhead=dot]; - 321 -> "362E" [label=" ", color=blue, arrowhead=dot]; - 321 -> "372E" [label=" ", color=blue, arrowhead=dot]; - 321 -> "572E" [label=" ", color=blue, arrowhead=dot]; - 322 -> "54E" [label=" ", color=blue, arrowhead=dot]; - 322 -> "222E" [label=" ", color=blue, arrowhead=dot]; - 322 -> "302E" [label=" ", color=blue, arrowhead=dot]; - 322 -> "556E" [label=" ", color=blue, arrowhead=dot]; - 322 -> "558E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "37E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "208E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "210E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "352E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "450E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "568E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "576E" [label=" ", color=blue, arrowhead=dot]; - 323 -> "686E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "228E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "248E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "304E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "468E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "578E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "660E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "688E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "694E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "714E" [label=" ", color=blue, arrowhead=dot]; - 324 -> "766E" [label=" ", color=blue, arrowhead=dot]; - 325 -> "97E" [label=" ", color=blue, arrowhead=dot]; - 325 -> "506E" [label=" ", color=blue, arrowhead=dot]; - 326 -> "61E" [label=" ", color=blue, arrowhead=dot]; - 326 -> "175E" [label=" ", color=blue, arrowhead=dot]; - 326 -> "482E" [label=" ", color=blue, arrowhead=dot]; - 328 -> "75E" [label=" ", color=blue, arrowhead=dot]; - 328 -> "580E" [label=" ", color=blue, arrowhead=dot]; - 329 -> "96E" [label=" ", color=blue, arrowhead=dot]; - 330 -> "100E" [label=" ", color=blue, arrowhead=dot]; - 330 -> "170E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "63E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "67E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "68E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "69E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "70E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "71E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "802E" [label=" ", color=blue, arrowhead=dot]; - 333 -> "793E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "64E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "81E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "82E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "83E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "84E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "85E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "86E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "87E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "88E" [label=" ", color=blue, arrowhead=dot]; - 334 -> "89E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "1E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "2E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "3E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "4E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "5E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "6E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "7E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "8E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "9E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "10E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "11E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "12E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "13E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "14E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "15E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "16E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "17E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "18E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "19E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "20E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "21E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "22E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "23E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "24E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "25E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "26E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "27E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "28E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "29E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "30E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "31E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "65E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "119E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "150E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "176E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "743E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "744E" [label=" ", color=blue, arrowhead=dot]; - 336 -> "764E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "120E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "121E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "122E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "123E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "124E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "125E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "126E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "127E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "128E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "129E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "130E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "131E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "132E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "133E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "134E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "135E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "136E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "137E" [label=" ", color=blue, arrowhead=dot]; - 337 -> "138E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "151E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "153E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "154E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "155E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "156E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "157E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "158E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "159E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "160E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "161E" [label=" ", color=blue, arrowhead=dot]; - 339 -> "162E" [label=" ", color=blue, arrowhead=dot]; - 347 -> "139E" [label=" ", color=blue, arrowhead=dot]; - 347 -> "795E" [label=" ", color=blue, arrowhead=dot]; - 348 -> "799E" [label=" ", color=blue, arrowhead=dot]; - 348 -> "800E" [label=" ", color=blue, arrowhead=dot]; - 349 -> "141E" [label=" ", color=blue, arrowhead=dot]; - 350 -> "142E" [label=" ", color=blue, arrowhead=dot]; - 350 -> "678E" [label=" ", color=blue, arrowhead=dot]; - 351 -> "143E" [label=" ", color=blue, arrowhead=dot]; - 351 -> "232E" [label=" ", color=blue, arrowhead=dot]; - 351 -> "680E" [label=" ", color=blue, arrowhead=dot]; - 351 -> "704E" [label=" ", color=blue, arrowhead=dot]; - 352 -> "144E" [label=" ", color=blue, arrowhead=dot]; - 352 -> "432E" [label=" ", color=blue, arrowhead=dot]; - 353 -> "145E" [label=" ", color=blue, arrowhead=dot]; - 354 -> "146E" [label=" ", color=blue, arrowhead=dot]; - 354 -> "396E" [label=" ", color=blue, arrowhead=dot]; - 355 -> "147E" [label=" ", color=blue, arrowhead=dot]; - 356 -> "148E" [label=" ", color=blue, arrowhead=dot]; - 357 -> "149E" [label=" ", color=blue, arrowhead=dot]; - 358 -> "167E" [label=" ", color=blue, arrowhead=dot]; - 359 -> "169E" [label=" ", color=blue, arrowhead=dot]; - 360 -> "171E" [label=" ", color=blue, arrowhead=dot]; - 361 -> "172E" [label=" ", color=blue, arrowhead=dot]; - 362 -> "173E" [label=" ", color=blue, arrowhead=dot]; - 363 -> "174E" [label=" ", color=blue, arrowhead=dot]; - 364 -> "101E" [label=" ", color=blue, arrowhead=dot]; - 365 -> "102E" [label=" ", color=blue, arrowhead=dot]; - 367 -> "104E" [label=" ", color=blue, arrowhead=dot]; - 368 -> "105E" [label=" ", color=blue, arrowhead=dot]; - 369 -> "106E" [label=" ", color=blue, arrowhead=dot]; - 374 -> "111E" [label=" ", color=blue, arrowhead=dot]; - 375 -> "112E" [label=" ", color=blue, arrowhead=dot]; - 377 -> "114E" [label=" ", color=blue, arrowhead=dot]; - 378 -> "115E" [label=" ", color=blue, arrowhead=dot]; - 380 -> "117E" [label=" ", color=blue, arrowhead=dot]; - 380 -> "392E" [label=" ", color=blue, arrowhead=dot]; - 381 -> "118E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "177E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "178E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "179E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "180E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "181E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "182E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "183E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "184E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "185E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "186E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "187E" [label=" ", color=blue, arrowhead=dot]; - 382 -> "188E" [label=" ", color=blue, arrowhead=dot]; - 383 -> "730E" [label=" ", color=blue, arrowhead=dot]; - 383 -> "732E" [label=" ", color=blue, arrowhead=dot]; - 383 -> "741E" [label=" ", color=blue, arrowhead=dot]; - 383 -> "765E" [label=" ", color=blue, arrowhead=dot]; - 383 -> "796E" [label=" ", color=blue, arrowhead=dot]; - 384 -> "726E" [label=" ", color=blue, arrowhead=dot]; - 384 -> "728E" [label=" ", color=blue, arrowhead=dot]; - 384 -> "742E" [label=" ", color=blue, arrowhead=dot]; - "1E" -> "34E" [color=purple, arrowhead=none]; - "2E" -> "35E" [color=purple, arrowhead=none]; - "3E" -> "36E" [color=purple, arrowhead=none]; - "4E" -> "37E" [color=purple, arrowhead=none]; - "5E" -> "38E" [color=purple, arrowhead=none]; - "6E" -> "39E" [color=purple, arrowhead=none]; - "7E" -> "40E" [color=purple, arrowhead=none]; - "9E" -> "41E" [color=purple, arrowhead=none]; - "10E" -> "42E" [color=purple, arrowhead=none]; - "11E" -> "43E" [color=purple, arrowhead=none]; - "12E" -> "44E" [color=purple, arrowhead=none]; - "13E" -> "45E" [color=purple, arrowhead=none]; - "14E" -> "46E" [color=purple, arrowhead=none]; - "15E" -> "47E" [color=purple, arrowhead=none]; - "16E" -> "48E" [color=purple, arrowhead=none]; - "49E" -> "17E" [color=purple, arrowhead=none]; - "18E" -> "50E" [color=purple, arrowhead=none]; - "19E" -> "51E" [color=purple, arrowhead=none]; - "20E" -> "52E" [color=purple, arrowhead=none]; - "21E" -> "53E" [color=purple, arrowhead=none]; - "22E" -> "54E" [color=purple, arrowhead=none]; - "23E" -> "55E" [color=purple, arrowhead=none]; - "24E" -> "56E" [color=purple, arrowhead=none]; - "25E" -> "57E" [color=purple, arrowhead=none]; - "26E" -> "58E" [color=purple, arrowhead=none]; - "27E" -> "59E" [color=purple, arrowhead=none]; - "28E" -> "60E" [color=purple, arrowhead=none]; - "29E" -> "61E" [color=purple, arrowhead=none]; - "30E" -> "62E" [color=purple, arrowhead=none]; - "31E" -> "63E" [color=purple, arrowhead=none]; - "64E" -> "65E" [color=purple, arrowhead=none]; - "66E" -> "8E" [color=purple, arrowhead=none]; - "71E" -> "76E" [color=purple, arrowhead=none]; - "67E" -> "72E" [color=purple, arrowhead=none]; - "68E" -> "73E" [color=purple, arrowhead=none]; - "69E" -> "74E" [color=purple, arrowhead=none]; - "70E" -> "75E" [color=purple, arrowhead=none]; - "81E" -> "92E" [color=purple, arrowhead=none]; - "82E" -> "93E" [color=purple, arrowhead=none]; - "83E" -> "94E" [color=purple, arrowhead=none]; - "84E" -> "95E" [color=purple, arrowhead=none]; - "85E" -> "96E" [color=purple, arrowhead=none]; - "86E" -> "97E" [color=purple, arrowhead=none]; - "87E" -> "98E" [color=purple, arrowhead=none]; - "88E" -> "99E" [color=purple, arrowhead=none]; - "89E" -> "100E" [color=purple, arrowhead=none]; - "101E" -> "120E" [color=purple, arrowhead=none]; - "102E" -> "121E" [color=purple, arrowhead=none]; - "103E" -> "122E" [color=purple, arrowhead=none]; - "104E" -> "123E" [color=purple, arrowhead=none]; - "105E" -> "124E" [color=purple, arrowhead=none]; - "106E" -> "125E" [color=purple, arrowhead=none]; - "107E" -> "126E" [color=purple, arrowhead=none]; - "108E" -> "127E" [color=purple, arrowhead=none]; - "109E" -> "128E" [color=purple, arrowhead=none]; - "110E" -> "129E" [color=purple, arrowhead=none]; - "111E" -> "130E" [color=purple, arrowhead=none]; - "112E" -> "131E" [color=purple, arrowhead=none]; - "113E" -> "132E" [color=purple, arrowhead=none]; - "114E" -> "133E" [color=purple, arrowhead=none]; - "115E" -> "134E" [color=purple, arrowhead=none]; - "116E" -> "135E" [color=purple, arrowhead=none]; - "117E" -> "136E" [color=purple, arrowhead=none]; - "118E" -> "137E" [color=purple, arrowhead=none]; - "119E" -> "138E" [color=purple, arrowhead=none]; - "139E" -> "151E" [color=purple, arrowhead=none]; - "141E" -> "153E" [color=purple, arrowhead=none]; - "142E" -> "154E" [color=purple, arrowhead=none]; - "143E" -> "155E" [color=purple, arrowhead=none]; - "144E" -> "156E" [color=purple, arrowhead=none]; - "145E" -> "157E" [color=purple, arrowhead=none]; - "146E" -> "158E" [color=purple, arrowhead=none]; - "147E" -> "159E" [color=purple, arrowhead=none]; - "148E" -> "160E" [color=purple, arrowhead=none]; - "149E" -> "161E" [color=purple, arrowhead=none]; - "150E" -> "162E" [color=purple, arrowhead=none]; - "165E" -> "177E" [color=purple, arrowhead=none]; - "166E" -> "178E" [color=purple, arrowhead=none]; - "167E" -> "179E" [color=purple, arrowhead=none]; - "168E" -> "180E" [color=purple, arrowhead=none]; - "169E" -> "181E" [color=purple, arrowhead=none]; - "170E" -> "182E" [color=purple, arrowhead=none]; - "171E" -> "183E" [color=purple, arrowhead=none]; - "172E" -> "184E" [color=purple, arrowhead=none]; - "173E" -> "185E" [color=purple, arrowhead=none]; - "174E" -> "186E" [color=purple, arrowhead=none]; - "175E" -> "187E" [color=purple, arrowhead=none]; - "176E" -> "188E" [color=purple, arrowhead=none]; - "189E" -> "190E" [color=purple, arrowhead=none]; - "191E" -> "192E" [color=purple, arrowhead=none]; - "193E" -> "194E" [color=purple, arrowhead=none]; - "195E" -> "196E" [color=purple, arrowhead=none]; - "197E" -> "198E" [color=purple, arrowhead=none]; - "199E" -> "200E" [color=purple, arrowhead=none]; - "201E" -> "202E" [color=purple, arrowhead=none]; - "203E" -> "204E" [color=purple, arrowhead=none]; - "205E" -> "206E" [color=purple, arrowhead=none]; - "207E" -> "208E" [color=purple, arrowhead=none]; - "209E" -> "210E" [color=purple, arrowhead=none]; - "412E" -> "211E" [color=purple, arrowhead=none]; - "214E" -> "213E" [color=purple, arrowhead=none]; - "216E" -> "215E" [color=purple, arrowhead=none]; - "217E" -> "218E" [color=purple, arrowhead=none]; - "219E" -> "220E" [color=purple, arrowhead=none]; - "221E" -> "222E" [color=purple, arrowhead=none]; - "223E" -> "224E" [color=purple, arrowhead=none]; - "225E" -> "226E" [color=purple, arrowhead=none]; - "227E" -> "228E" [color=purple, arrowhead=none]; - "231E" -> "232E" [color=purple, arrowhead=none]; - "233E" -> "234E" [color=purple, arrowhead=none]; - "236E" -> "235E" [color=purple, arrowhead=none]; - "237E" -> "238E" [color=purple, arrowhead=none]; - "239E" -> "240E" [color=purple, arrowhead=none]; - "241E" -> "242E" [color=purple, arrowhead=none]; - "243E" -> "244E" [color=purple, arrowhead=none]; - "245E" -> "246E" [color=purple, arrowhead=none]; - "247E" -> "248E" [color=purple, arrowhead=none]; - "249E" -> "250E" [color=purple, arrowhead=none]; - "251E" -> "252E" [color=purple, arrowhead=none]; - "253E" -> "254E" [color=purple, arrowhead=none]; - "255E" -> "256E" [color=purple, arrowhead=none]; - "257E" -> "258E" [color=purple, arrowhead=none]; - "259E" -> "260E" [color=purple, arrowhead=none]; - "261E" -> "262E" [color=purple, arrowhead=none]; - "263E" -> "264E" [color=purple, arrowhead=none]; - "265E" -> "266E" [color=purple, arrowhead=none]; - "267E" -> "268E" [color=purple, arrowhead=none]; - "269E" -> "270E" [color=purple, arrowhead=none]; - "271E" -> "272E" [color=purple, arrowhead=none]; - "273E" -> "274E" [color=purple, arrowhead=none]; - "275E" -> "276E" [color=purple, arrowhead=none]; - "278E" -> "277E" [color=purple, arrowhead=none]; - "279E" -> "767E" [color=purple, arrowhead=none]; - "281E" -> "282E" [color=purple, arrowhead=none]; - "283E" -> "284E" [color=purple, arrowhead=none]; - "285E" -> "286E" [color=purple, arrowhead=none]; - "768E" -> "287E" [color=purple, arrowhead=none]; - "289E" -> "290E" [color=purple, arrowhead=none]; - "291E" -> "292E" [color=purple, arrowhead=none]; - "293E" -> "294E" [color=purple, arrowhead=none]; - "295E" -> "296E" [color=purple, arrowhead=none]; - "297E" -> "298E" [color=purple, arrowhead=none]; - "299E" -> "300E" [color=purple, arrowhead=none]; - "301E" -> "302E" [color=purple, arrowhead=none]; - "303E" -> "304E" [color=purple, arrowhead=none]; - "305E" -> "306E" [color=purple, arrowhead=none]; - "307E" -> "308E" [color=purple, arrowhead=none]; - "309E" -> "310E" [color=purple, arrowhead=none]; - "311E" -> "312E" [color=purple, arrowhead=none]; - "313E" -> "314E" [color=purple, arrowhead=none]; - "315E" -> "316E" [color=purple, arrowhead=none]; - "317E" -> "318E" [color=purple, arrowhead=none]; - "319E" -> "320E" [color=purple, arrowhead=none]; - "321E" -> "322E" [color=purple, arrowhead=none]; - "327E" -> "800E" [color=purple, arrowhead=none]; - "329E" -> "330E" [color=purple, arrowhead=none]; - "331E" -> "332E" [color=purple, arrowhead=none]; - "333E" -> "334E" [color=purple, arrowhead=none]; - "335E" -> "336E" [color=purple, arrowhead=none]; - "337E" -> "338E" [color=purple, arrowhead=none]; - "339E" -> "340E" [color=purple, arrowhead=none]; - "341E" -> "342E" [color=purple, arrowhead=none]; - "343E" -> "344E" [color=purple, arrowhead=none]; - "345E" -> "346E" [color=purple, arrowhead=none]; - "347E" -> "348E" [color=purple, arrowhead=none]; - "349E" -> "350E" [color=purple, arrowhead=none]; - "351E" -> "352E" [color=purple, arrowhead=none]; - "353E" -> "354E" [color=purple, arrowhead=none]; - "412E" -> "355E" [color=purple, arrowhead=none]; - "357E" -> "358E" [color=purple, arrowhead=none]; - "359E" -> "360E" [color=purple, arrowhead=none]; - "361E" -> "362E" [color=purple, arrowhead=none]; - "363E" -> "364E" [color=purple, arrowhead=none]; - "365E" -> "366E" [color=purple, arrowhead=none]; - "367E" -> "368E" [color=purple, arrowhead=none]; - "369E" -> "370E" [color=purple, arrowhead=none]; - "371E" -> "372E" [color=purple, arrowhead=none]; - "373E" -> "374E" [color=purple, arrowhead=none]; - "375E" -> "376E" [color=purple, arrowhead=none]; - "377E" -> "378E" [color=purple, arrowhead=none]; - "379E" -> "380E" [color=purple, arrowhead=none]; - "381E" -> "382E" [color=purple, arrowhead=none]; - "383E" -> "384E" [color=purple, arrowhead=none]; - "385E" -> "386E" [color=purple, arrowhead=none]; - "387E" -> "388E" [color=purple, arrowhead=none]; - "389E" -> "390E" [color=purple, arrowhead=none]; - "391E" -> "392E" [color=purple, arrowhead=none]; - "393E" -> "394E" [color=purple, arrowhead=none]; - "395E" -> "396E" [color=purple, arrowhead=none]; - "397E" -> "398E" [color=purple, arrowhead=none]; - "399E" -> "400E" [color=purple, arrowhead=none]; - "402E" -> "401E" [color=purple, arrowhead=none]; - "404E" -> "403E" [color=purple, arrowhead=none]; - "406E" -> "405E" [color=purple, arrowhead=none]; - "408E" -> "407E" [color=purple, arrowhead=none]; - "236E" -> "409E" [color=purple, arrowhead=none]; - "412E" -> "411E" [color=purple, arrowhead=none]; - "412E" -> "413E" [color=purple, arrowhead=none]; - "278E" -> "415E" [color=purple, arrowhead=none]; - "417E" -> "418E" [color=purple, arrowhead=none]; - "419E" -> "420E" [color=purple, arrowhead=none]; - "421E" -> "422E" [color=purple, arrowhead=none]; - "423E" -> "424E" [color=purple, arrowhead=none]; - "425E" -> "426E" [color=purple, arrowhead=none]; - "427E" -> "428E" [color=purple, arrowhead=none]; - "431E" -> "432E" [color=purple, arrowhead=none]; - "433E" -> "434E" [color=purple, arrowhead=none]; - "435E" -> "436E" [color=purple, arrowhead=none]; - "438E" -> "437E" [color=purple, arrowhead=none]; - "439E" -> "440E" [color=purple, arrowhead=none]; - "441E" -> "442E" [color=purple, arrowhead=none]; - "443E" -> "444E" [color=purple, arrowhead=none]; - "445E" -> "446E" [color=purple, arrowhead=none]; - "448E" -> "447E" [color=purple, arrowhead=none]; - "449E" -> "450E" [color=purple, arrowhead=none]; - "451E" -> "452E" [color=purple, arrowhead=none]; - "453E" -> "454E" [color=purple, arrowhead=none]; - "455E" -> "456E" [color=purple, arrowhead=none]; - "457E" -> "458E" [color=purple, arrowhead=none]; - "459E" -> "460E" [color=purple, arrowhead=none]; - "461E" -> "462E" [color=purple, arrowhead=none]; - "236E" -> "463E" [color=purple, arrowhead=none]; - "465E" -> "466E" [color=purple, arrowhead=none]; - "467E" -> "468E" [color=purple, arrowhead=none]; - "469E" -> "470E" [color=purple, arrowhead=none]; - "471E" -> "472E" [color=purple, arrowhead=none]; - "473E" -> "474E" [color=purple, arrowhead=none]; - "476E" -> "475E" [color=purple, arrowhead=none]; - "477E" -> "478E" [color=purple, arrowhead=none]; - "479E" -> "358E" [color=purple, arrowhead=none]; - "481E" -> "482E" [color=purple, arrowhead=none]; - "483E" -> "484E" [color=purple, arrowhead=none]; - "485E" -> "486E" [color=purple, arrowhead=none]; - "487E" -> "488E" [color=purple, arrowhead=none]; - "489E" -> "490E" [color=purple, arrowhead=none]; - "491E" -> "492E" [color=purple, arrowhead=none]; - "495E" -> "795E" [color=purple, arrowhead=none]; - "499E" -> "500E" [color=purple, arrowhead=none]; - "501E" -> "502E" [color=purple, arrowhead=none]; - "504E" -> "503E" [color=purple, arrowhead=none]; - "505E" -> "506E" [color=purple, arrowhead=none]; - "507E" -> "508E" [color=purple, arrowhead=none]; - "509E" -> "510E" [color=purple, arrowhead=none]; - "412E" -> "511E" [color=purple, arrowhead=none]; - "513E" -> "514E" [color=purple, arrowhead=none]; - "515E" -> "516E" [color=purple, arrowhead=none]; - "517E" -> "518E" [color=purple, arrowhead=none]; - "519E" -> "520E" [color=purple, arrowhead=none]; - "521E" -> "522E" [color=purple, arrowhead=none]; - "523E" -> "524E" [color=purple, arrowhead=none]; - "525E" -> "526E" [color=purple, arrowhead=none]; - "527E" -> "528E" [color=purple, arrowhead=none]; - "529E" -> "530E" [color=purple, arrowhead=none]; - "531E" -> "532E" [color=purple, arrowhead=none]; - "533E" -> "534E" [color=purple, arrowhead=none]; - "535E" -> "536E" [color=purple, arrowhead=none]; - "537E" -> "538E" [color=purple, arrowhead=none]; - "539E" -> "540E" [color=purple, arrowhead=none]; - "541E" -> "542E" [color=purple, arrowhead=none]; - "543E" -> "544E" [color=purple, arrowhead=none]; - "545E" -> "546E" [color=purple, arrowhead=none]; - "547E" -> "548E" [color=purple, arrowhead=none]; - "549E" -> "550E" [color=purple, arrowhead=none]; - "551E" -> "552E" [color=purple, arrowhead=none]; - "553E" -> "554E" [color=purple, arrowhead=none]; - "555E" -> "556E" [color=purple, arrowhead=none]; - "557E" -> "558E" [color=purple, arrowhead=none]; - "278E" -> "559E" [color=purple, arrowhead=none]; - "561E" -> "562E" [color=purple, arrowhead=none]; - "563E" -> "564E" [color=purple, arrowhead=none]; - "565E" -> "566E" [color=purple, arrowhead=none]; - "567E" -> "568E" [color=purple, arrowhead=none]; - "569E" -> "570E" [color=purple, arrowhead=none]; - "571E" -> "572E" [color=purple, arrowhead=none]; - "573E" -> "574E" [color=purple, arrowhead=none]; - "575E" -> "576E" [color=purple, arrowhead=none]; - "577E" -> "578E" [color=purple, arrowhead=none]; - "579E" -> "580E" [color=purple, arrowhead=none]; - "581E" -> "582E" [color=purple, arrowhead=none]; - "583E" -> "584E" [color=purple, arrowhead=none]; - "585E" -> "586E" [color=purple, arrowhead=none]; - "587E" -> "588E" [color=purple, arrowhead=none]; - "589E" -> "590E" [color=purple, arrowhead=none]; - "597E" -> "598E" [color=purple, arrowhead=none]; - "599E" -> "600E" [color=purple, arrowhead=none]; - "601E" -> "602E" [color=purple, arrowhead=none]; - "603E" -> "604E" [color=purple, arrowhead=none]; - "605E" -> "606E" [color=purple, arrowhead=none]; - "607E" -> "608E" [color=purple, arrowhead=none]; - "609E" -> "610E" [color=purple, arrowhead=none]; - "611E" -> "612E" [color=purple, arrowhead=none]; - "613E" -> "614E" [color=purple, arrowhead=none]; - "615E" -> "358E" [color=purple, arrowhead=none]; - "617E" -> "618E" [color=purple, arrowhead=none]; - "619E" -> "620E" [color=purple, arrowhead=none]; - "623E" -> "624E" [color=purple, arrowhead=none]; - "625E" -> "626E" [color=purple, arrowhead=none]; - "627E" -> "628E" [color=purple, arrowhead=none]; - "629E" -> "630E" [color=purple, arrowhead=none]; - "631E" -> "632E" [color=purple, arrowhead=none]; - "634E" -> "633E" [color=purple, arrowhead=none]; - "635E" -> "636E" [color=purple, arrowhead=none]; - "637E" -> "638E" [color=purple, arrowhead=none]; - "639E" -> "640E" [color=purple, arrowhead=none]; - "641E" -> "642E" [color=purple, arrowhead=none]; - "643E" -> "644E" [color=purple, arrowhead=none]; - "645E" -> "646E" [color=purple, arrowhead=none]; - "647E" -> "648E" [color=purple, arrowhead=none]; - "649E" -> "650E" [color=purple, arrowhead=none]; - "651E" -> "652E" [color=purple, arrowhead=none]; - "653E" -> "654E" [color=purple, arrowhead=none]; - "655E" -> "656E" [color=purple, arrowhead=none]; - "657E" -> "658E" [color=purple, arrowhead=none]; - "659E" -> "660E" [color=purple, arrowhead=none]; - "661E" -> "662E" [color=purple, arrowhead=none]; - "663E" -> "664E" [color=purple, arrowhead=none]; - "665E" -> "666E" [color=purple, arrowhead=none]; - "667E" -> "668E" [color=purple, arrowhead=none]; - "669E" -> "670E" [color=purple, arrowhead=none]; - "671E" -> "672E" [color=purple, arrowhead=none]; - "673E" -> "674E" [color=purple, arrowhead=none]; - "675E" -> "676E" [color=purple, arrowhead=none]; - "679E" -> "680E" [color=purple, arrowhead=none]; - "681E" -> "682E" [color=purple, arrowhead=none]; - "683E" -> "684E" [color=purple, arrowhead=none]; - "685E" -> "686E" [color=purple, arrowhead=none]; - "687E" -> "688E" [color=purple, arrowhead=none]; - "689E" -> "690E" [color=purple, arrowhead=none]; - "691E" -> "692E" [color=purple, arrowhead=none]; - "693E" -> "694E" [color=purple, arrowhead=none]; - "695E" -> "696E" [color=purple, arrowhead=none]; - "697E" -> "698E" [color=purple, arrowhead=none]; - "699E" -> "700E" [color=purple, arrowhead=none]; - "703E" -> "704E" [color=purple, arrowhead=none]; - "705E" -> "706E" [color=purple, arrowhead=none]; - "709E" -> "710E" [color=purple, arrowhead=none]; - "711E" -> "712E" [color=purple, arrowhead=none]; - "713E" -> "714E" [color=purple, arrowhead=none]; - "715E" -> "398E" [color=purple, arrowhead=none]; - "717E" -> "718E" [color=purple, arrowhead=none]; - "719E" -> "720E" [color=purple, arrowhead=none]; - "721E" -> "722E" [color=purple, arrowhead=none]; - "725E" -> "726E" [color=purple, arrowhead=none]; - "727E" -> "728E" [color=purple, arrowhead=none]; - "729E" -> "730E" [color=purple, arrowhead=none]; - "731E" -> "732E" [color=purple, arrowhead=none]; - "741E" -> "743E" [color=purple, arrowhead=none]; - "742E" -> "744E" [color=purple, arrowhead=none]; - "763E" -> "764E" [color=purple, arrowhead=none]; - "765E" -> "766E" [color=purple, arrowhead=none]; - "770E" -> "783E" [color=purple, arrowhead=none]; - "770E" -> "784E" [color=purple, arrowhead=none]; - "769E" -> "785E" [color=purple, arrowhead=none]; - "769E" -> "786E" [color=purple, arrowhead=none]; - "769E" -> "787E" [color=purple, arrowhead=none]; - "770E" -> "788E" [color=purple, arrowhead=none]; - "770E" -> "789E" [color=purple, arrowhead=none]; - "769E" -> "790E" [color=purple, arrowhead=none]; - "770E" -> "791E" [color=purple, arrowhead=none]; - "769E" -> "792E" [color=purple, arrowhead=none]; - "793E" -> "769E" [color=purple, arrowhead=none]; - "769E" -> "784E" [color=purple, arrowhead=none]; - "770E" -> "785E" [color=purple, arrowhead=none]; - "788E" -> "787E" [color=purple, arrowhead=none]; - "770E" -> "792E" [color=purple, arrowhead=none]; - "798E" -> "799E" [color=purple, arrowhead=none]; - "796E" -> "797E" [color=purple, arrowhead=none]; - "793E" -> "789E" [color=purple, arrowhead=none]; - "783E" -> "787E" [color=purple, arrowhead=none]; - "784E" -> "792E" [color=purple, arrowhead=none]; - "787E" -> "789E" [color=purple, arrowhead=none]; - "769E" -> "791E" [color=purple, arrowhead=none]; - "802E" -> "801E" [color=purple, arrowhead=none]; -} diff --git a/dot/2.dot b/dot/2.dot deleted file mode 100644 index fa95abc..0000000 --- a/dot/2.dot +++ /dev/null @@ -1,27 +0,0 @@ -digraph G { - - subgraph cluster_0 { - style=filled; - color=lightgrey; - node [style=filled,color=white]; - a0 -> a1 -> a2 -> a3; - label = "process #1"; - } - - subgraph cluster_1 { - node [style=filled]; - b0 -> b1 -> b2 -> b3; - label = "process #2"; - color=blue - } - start -> a0; - start -> b0; - a1 -> b3; - b2 -> a3; - a3 -> a0; - a3 -> end; - b3 -> end; - - start [shape=Mdiamond]; - end [shape=Msquare]; -} diff --git a/dot/3.dot b/dot/3.dot deleted file mode 100644 index b51d498..0000000 --- a/dot/3.dot +++ /dev/null @@ -1,104 +0,0 @@ -digraph "unix" { - graph [ fontname = "Helvetica-Oblique", - fontsize = 36, - label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93", - size = "6,6" ]; - node [ shape = polygon, - sides = 4, - distortion = "0.0", - orientation = "0.0", - skew = "0.0", - color = white, - style = filled, - fontname = "Helvetica-Outline" ]; - "5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2]; - "6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue]; - "PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2]; - LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2]; - "1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1]; - "Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow]; - Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen]; - Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1]; - "Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2]; - "PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3]; - "7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate]; - "8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3]; - "32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3]; - V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy]; - "Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4]; - Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral]; - "UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3]; - "9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3]; - "2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond]; - "2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1]; - "2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2]; - "3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon]; - "4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1]; - "4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1]; - "4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4]; - "4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2]; - "Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3]; - "PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan]; - "USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue]; - "CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick]; - "USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4]; - "CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow]; - "CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4]; - "Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2]; - "PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1]; - "USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2]; - "Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered]; - "TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson]; - "System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1]; - "System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4]; - "System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1]; - "5th Edition" -> "6th Edition"; - "5th Edition" -> "PWB 1.0"; - "6th Edition" -> LSX; - "6th Edition" -> "1 BSD"; - "6th Edition" -> "Mini Unix"; - "6th Edition" -> Wollongong; - "6th Edition" -> Interdata; - Interdata -> "Unix/TS 3.0"; - Interdata -> "PWB 2.0"; - Interdata -> "7th Edition"; - "7th Edition" -> "8th Edition"; - "7th Edition" -> "32V"; - "7th Edition" -> V7M; - "7th Edition" -> "Ultrix-11"; - "7th Edition" -> Xenix; - "7th Edition" -> "UniPlus+"; - V7M -> "Ultrix-11"; - "8th Edition" -> "9th Edition"; - "1 BSD" -> "2 BSD"; - "2 BSD" -> "2.8 BSD"; - "2.8 BSD" -> "Ultrix-11"; - "2.8 BSD" -> "2.9 BSD"; - "32V" -> "3 BSD"; - "3 BSD" -> "4 BSD"; - "4 BSD" -> "4.1 BSD"; - "4.1 BSD" -> "4.2 BSD"; - "4.1 BSD" -> "2.8 BSD"; - "4.1 BSD" -> "8th Edition"; - "4.2 BSD" -> "4.3 BSD"; - "4.2 BSD" -> "Ultrix-32"; - "PWB 1.0" -> "PWB 1.2"; - "PWB 1.0" -> "USG 1.0"; - "PWB 1.2" -> "PWB 2.0"; - "USG 1.0" -> "CB Unix 1"; - "USG 1.0" -> "USG 2.0"; - "CB Unix 1" -> "CB Unix 2"; - "CB Unix 2" -> "CB Unix 3"; - "CB Unix 3" -> "Unix/TS++"; - "CB Unix 3" -> "PDP-11 Sys V"; - "USG 2.0" -> "USG 3.0"; - "USG 3.0" -> "Unix/TS 3.0"; - "PWB 2.0" -> "Unix/TS 3.0"; - "Unix/TS 1.0" -> "Unix/TS 3.0"; - "Unix/TS 3.0" -> "TS 4.0"; - "Unix/TS++" -> "TS 4.0"; - "CB Unix 3" -> "TS 4.0"; - "TS 4.0" -> "System V.0"; - "System V.0" -> "System V.2"; - "System V.2" -> "System V.3"; -} diff --git a/dot/4.dot b/dot/4.dot deleted file mode 100644 index e59b7c2..0000000 --- a/dot/4.dot +++ /dev/null @@ -1,20 +0,0 @@ -digraph finite_state_machine { - rankdir=LR; - size="8,5" - node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; - node [shape = circle]; - LR_0 -> LR_2 [ label = "SS(B)" ]; - LR_0 -> LR_1 [ label = "SS(S)" ]; - LR_1 -> LR_3 [ label = "S($end)" ]; - LR_2 -> LR_6 [ label = "SS(b)" ]; - LR_2 -> LR_5 [ label = "SS(a)" ]; - LR_2 -> LR_4 [ label = "S(A)" ]; - LR_5 -> LR_7 [ label = "S(b)" ]; - LR_5 -> LR_5 [ label = "S(a)" ]; - LR_6 -> LR_6 [ label = "S(b)" ]; - LR_6 -> LR_5 [ label = "S(a)" ]; - LR_7 -> LR_8 [ label = "S(b)" ]; - LR_7 -> LR_5 [ label = "S(a)" ]; - LR_8 -> LR_6 [ label = "S(b)" ]; - LR_8 -> LR_5 [ label = "S(a)" ]; -} diff --git a/dot/5.dot b/dot/5.dot deleted file mode 100644 index 72b28fa..0000000 --- a/dot/5.dot +++ /dev/null @@ -1,2212 +0,0 @@ -digraph G { - ranksep=3; - ratio=auto; -"1" [ label="02f5daf56e299b8a8ecea892",shape="hexagon",style="filled",color="green" ]; -"189E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; -"790E" [ label="b4dfef6",shape="box",style="filled",color="grey" ]; -"2" [ label="171192dc1f8e6ea551548a910c00",shape="hexagon",style="filled",color="green" ]; -"191E" [ label="629e42",shape="box",style="filled",color="grey" ]; -"3" [ label="6bce02baf91781a831e1b95",shape="hexagon",style="filled",color="green" ]; -"193E" [ label="1c08373",shape="box",style="filled",color="grey" ]; -"4" [ label="6236a67933a619a6a3d48",shape="hexagon",style="filled",color="green" ]; -"195E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; -"5" [ label="50962c93b4cb293f5beb59eb",shape="hexagon",style="filled",color="green" ]; -"197E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; -"6" [ label="05d4b1ed6a6135eec3abd3f2",shape="hexagon",style="filled",color="green" ]; -"199E" [ label="",shape="box",style="filled",color="grey" ]; -"7" [ label="08769f73d31c1a99be2d9363f",shape="hexagon",style="filled",color="green" ]; -"201E" [ label="629e42",shape="box",style="filled",color="grey" ]; -"8" [ label="a6a196a504c3a7657d1fa41",shape="hexagon",style="filled",color="green" ]; -"203E" [ label="cd856f",shape="box",style="filled",color="grey" ]; -"9" [ label="837ebf4bde22e1f1535cb662",shape="hexagon",style="filled",color="green" ]; -"725E" [ label="d0eb84",shape="box",style="filled",color="grey" ]; -"785E" [ label="dd2ba36",shape="box",style="filled",color="grey" ]; -"10" [ label="5f865c374cb3fe976dd376b8",shape="hexagon",style="filled",color="green" ]; -"205E" [ label="23ad1",shape="box",style="filled",color="grey" ]; -"11" [ label="8be752bc95d436a90493bec9",shape="hexagon",style="filled",color="green" ]; -"207E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; -"12" [ label="969a58db14386cb9d2f51ec",shape="hexagon",style="filled",color="green" ]; -"209E" [ label="7c7c",shape="box",style="filled",color="grey" ]; -"13" [ label="da24f74aad2ff519009d1f38c",shape="hexagon",style="filled",color="green" ]; -"211E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; -"14" [ label="3124d3a6ed3381a6341c6",shape="hexagon",style="filled",color="green" ]; -"213E" [ label="bbe0a8f93dc1",shape="box",style="filled",color="grey" ]; -"15" [ label="71512ec7d43f958f2b6da",shape="hexagon",style="filled",color="green" ]; -"215E" [ label="3f0a2b4eb62f",shape="box",style="filled",color="grey" ]; -"16" [ label="3828a2c682419423cf",shape="hexagon",style="filled",color="green" ]; -"727E" [ label="2",shape="box",style="filled",color="grey" ]; -"784E" [ label="",shape="box",style="filled",color="grey" ]; -"17" [ label="aa868f65c34cdb64f1fad19a",shape="hexagon",style="filled",color="green" ]; -"217E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; -"787E" [ label="1aaaab063",shape="box",style="filled",color="grey" ]; -"18" [ label="dca32af03698c988b22",shape="hexagon",style="filled",color="green" ]; -"219E" [ label="eb8",shape="box",style="filled",color="grey" ]; -"19" [ label="d8f4a9e463a1e89217f",shape="hexagon",style="filled",color="green" ]; -"221E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; -"20" [ label="c96782ef56711c5d6a3f69",shape="hexagon",style="filled",color="green" ]; -"223E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; -"21" [ label="4f04c39708f",shape="hexagon",style="filled",color="green" ]; -"225E" [ label="a49284e9",shape="box",style="filled",color="grey" ]; -"22" [ label="97284d4c3a5d499853f0e",shape="hexagon",style="filled",color="green" ]; -"227E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; -"792E" [ label="79b69c612",shape="box",style="filled",color="grey" ]; -"23" [ label="c4d32527b670afb370d643",shape="hexagon",style="filled",color="green" ]; -"231E" [ label="e851f5ddd920",shape="box",style="filled",color="grey" ]; -"24" [ label="5e9156098c064",shape="hexagon",style="filled",color="green" ]; -"233E" [ label="",shape="box",style="filled",color="grey" ]; -"25" [ label="3d475ea3aeca51b60212dd",shape="hexagon",style="filled",color="green" ]; -"235E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; -"26" [ label="966d271c22e75c7538",shape="hexagon",style="filled",color="green" ]; -"237E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"27" [ label="b630e1af6ae1997f0e8ba750",shape="hexagon",style="filled",color="green" ]; -"239E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; -"783E" [ label="499f6985db294c",shape="box",style="filled",color="grey" ]; -"28" [ label="ebd8ffc2ac3a90efb8af9",shape="hexagon",style="filled",color="green" ]; -"241E" [ label="1ebeec",shape="box",style="filled",color="grey" ]; -"791E" [ label="c0b727",shape="box",style="filled",color="grey" ]; -"29" [ label="69fdd1a1f4768c5efe7",shape="hexagon",style="filled",color="green" ]; -"243E" [ label="35b8742610",shape="box",style="filled",color="grey" ]; -"30" [ label="d93a80739fc1edb41a11b7294",shape="hexagon",style="filled",color="green" ]; -"245E" [ label="e03b8bc0435a",shape="box",style="filled",color="grey" ]; -"31" [ label="bf65cfddeb00ff847feae0c",shape="hexagon",style="filled",color="green" ]; -"247E" [ label="8df",shape="box",style="filled",color="grey" ]; -"32" [ label="916c686a1e82dba72524a",shape="hexagon",style="filled",color="green" ]; -"249E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; -"33" [ label="f496bcf0889b301d77819c",shape="hexagon",style="filled",color="green" ]; -"251E" [ label="f29dfb9",shape="box",style="filled",color="grey" ]; -"34" [ label="76889f7d35e",shape="hexagon",style="filled",color="green" ]; -"253E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; -"35" [ label="668d636002",shape="hexagon",style="filled",color="green" ]; -"255E" [ label="4379b5ed",shape="box",style="filled",color="grey" ]; -"36" [ label="e1e4c23db39d8bd633c3a",shape="hexagon",style="filled",color="green" ]; -"257E" [ label="1ed5d7f63b8c6",shape="box",style="filled",color="grey" ]; -"37" [ label="842bc5775657c1e0d67",shape="hexagon",style="filled",color="green" ]; -"259E" [ label="a387210a27b",shape="box",style="filled",color="grey" ]; -"38" [ label="e4e2f4e6d",shape="hexagon",style="filled",color="green" ]; -"261E" [ label="1f4f0fdf",shape="box",style="filled",color="grey" ]; -"39" [ label="04390dec6f1779353c07f5",shape="hexagon",style="filled",color="green" ]; -"263E" [ label="bac77c3f414a",shape="box",style="filled",color="grey" ]; -"40" [ label="69f2611acc42c36ed7cc",shape="hexagon",style="filled",color="green" ]; -"265E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"41" [ label="1562abef0d8241",shape="hexagon",style="filled",color="green" ]; -"267E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; -"42" [ label="e49aaa5cc4e44355d6a0",shape="hexagon",style="filled",color="green" ]; -"269E" [ label="cc3f63d",shape="box",style="filled",color="grey" ]; -"43" [ label="e8ebe1bf5f421c1223",shape="hexagon",style="filled",color="green" ]; -"271E" [ label="96325ea",shape="box",style="filled",color="grey" ]; -"44" [ label="2759e82e30d6d",shape="hexagon",style="filled",color="green" ]; -"273E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; -"45" [ label="23c1ec53358d237c1",shape="hexagon",style="filled",color="green" ]; -"275E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"46" [ label="5838586c293d455",shape="hexagon",style="filled",color="green" ]; -"277E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; -"47" [ label="f841118350a27b7ea29a9c9d",shape="hexagon",style="filled",color="green" ]; -"279E" [ label="69f4ecb77d",shape="box",style="filled",color="grey" ]; -"48" [ label="658d208447d8ec5d6de8",shape="hexagon",style="filled",color="green" ]; -"281E" [ label="f7b22b9640",shape="box",style="filled",color="grey" ]; -"49" [ label="11180ae7706510211bc4",shape="hexagon",style="filled",color="green" ]; -"283E" [ label="052bb6e3",shape="box",style="filled",color="grey" ]; -"50" [ label="5807acd8d58e006f43",shape="hexagon",style="filled",color="green" ]; -"285E" [ label="",shape="box",style="filled",color="grey" ]; -"51" [ label="fe4e848cb5291ee59a2",shape="hexagon",style="filled",color="green" ]; -"287E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; -"52" [ label="c4f31ea3844e12da27ad47c6",shape="hexagon",style="filled",color="green" ]; -"289E" [ label="fb16636aae",shape="box",style="filled",color="grey" ]; -"53" [ label="00cbeb87c182ca0785f",shape="hexagon",style="filled",color="green" ]; -"291E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; -"54" [ label="11f088bfd8",shape="hexagon",style="filled",color="green" ]; -"293E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; -"55" [ label="64a9ec24428099ad8ed82ba6",shape="hexagon",style="filled",color="green" ]; -"745E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; -"56" [ label="3c2a62e0e5e9f7",shape="hexagon",style="filled",color="green" ]; -"295E" [ label="ae32701",shape="box",style="filled",color="grey" ]; -"57" [ label="dd84fe6a65cfac7bca03ebd",shape="hexagon",style="filled",color="green" ]; -"297E" [ label="",shape="box",style="filled",color="grey" ]; -"58" [ label="b06bbfa920aa95dd",shape="hexagon",style="filled",color="green" ]; -"299E" [ label="07",shape="box",style="filled",color="grey" ]; -"59" [ label="6b5aaa4bdf44b2c898854",shape="hexagon",style="filled",color="green" ]; -"301E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; -"789E" [ label="3a0ff0",shape="box",style="filled",color="grey" ]; -"60" [ label="855d26296eda4eb7",shape="hexagon",style="filled",color="green" ]; -"303E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; -"61" [ label="e82f47b8d4949ba4af69b38cbc19",shape="hexagon",style="filled",color="green" ]; -"305E" [ label="b62cd1d0a0",shape="box",style="filled",color="grey" ]; -"62" [ label="86569bffb49adf6b3d0ebac",shape="hexagon",style="filled",color="green" ]; -"307E" [ label="660ffeb76fc59",shape="box",style="filled",color="grey" ]; -"63" [ label="a96e47ff37983425a3e452095",shape="hexagon",style="filled",color="green" ]; -"309E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"64" [ label="71a48d11b2e7e56b1df128bd",shape="hexagon",style="filled",color="green" ]; -"311E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; -"65" [ label="a0befe6dd1ca7b165786835",shape="hexagon",style="filled",color="green" ]; -"313E" [ label="3cfae",shape="box",style="filled",color="grey" ]; -"66" [ label="f33ec11db496f7bfcb024f",shape="hexagon",style="filled",color="green" ]; -"315E" [ label="71e6b",shape="box",style="filled",color="grey" ]; -"67" [ label="fe6be3206549f5b5564acde84783",shape="hexagon",style="filled",color="green" ]; -"317E" [ label="",shape="box",style="filled",color="grey" ]; -"68" [ label="e4dba079d5fcb1f165920a3bf",shape="hexagon",style="filled",color="green" ]; -"319E" [ label="",shape="box",style="filled",color="grey" ]; -"69" [ label="35dfbee3123dc389cba0b15",shape="hexagon",style="filled",color="green" ]; -"746E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; -"70" [ label="16c508ab98483d430bbe",shape="hexagon",style="filled",color="green" ]; -"321E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"71" [ label="9c9e2e0f2da8758e436c",shape="hexagon",style="filled",color="green" ]; -"327E" [ label="cd0d985a366cad7e",shape="box",style="filled",color="grey" ]; -"72" [ label="fb039d7a2a9fe73b5f468eba9",shape="hexagon",style="filled",color="green" ]; -"329E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"73" [ label="2ef949c4a39b",shape="hexagon",style="filled",color="green" ]; -"331E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; -"74" [ label="a9497e0757b0969bde707ed5",shape="hexagon",style="filled",color="green" ]; -"333E" [ label="541ab86a2e",shape="box",style="filled",color="grey" ]; -"75" [ label="230cc6bbc66b24eae94fa03d",shape="hexagon",style="filled",color="green" ]; -"335E" [ label="",shape="box",style="filled",color="grey" ]; -"76" [ label="1d163eac141def176461c",shape="hexagon",style="filled",color="green" ]; -"337E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; -"77" [ label="32979f8cf86",shape="hexagon",style="filled",color="green" ]; -"339E" [ label="a7e89580",shape="box",style="filled",color="grey" ]; -"78" [ label="37d80ae421dba4a70730338860",shape="hexagon",style="filled",color="green" ]; -"341E" [ label="",shape="box",style="filled",color="grey" ]; -"79" [ label="fbba7215e7c13173a60206",shape="hexagon",style="filled",color="green" ]; -"343E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; -"80" [ label="2dd8cc4d693415f93c0f8fc",shape="hexagon",style="filled",color="green" ]; -"345E" [ label="94da691e20e3",shape="box",style="filled",color="grey" ]; -"81" [ label="00880e6f50c765ebc1f85d3e9",shape="hexagon",style="filled",color="green" ]; -"347E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; -"82" [ label="ef13d45b1277ac9a0444adb",shape="hexagon",style="filled",color="green" ]; -"349E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; -"83" [ label="2573e1bf51f1b307f4640",shape="hexagon",style="filled",color="green" ]; -"351E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; -"84" [ label="162d8039483d8",shape="hexagon",style="filled",color="green" ]; -"353E" [ label="a8e9",shape="box",style="filled",color="grey" ]; -"85" [ label="f490de272a7f6e4af346d40",shape="hexagon",style="filled",color="green" ]; -"355E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; -"788E" [ label="391256c872",shape="box",style="filled",color="grey" ]; -"86" [ label="678bf739c344b9ad41da1",shape="hexagon",style="filled",color="green" ]; -"357E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; -"87" [ label="876d120b38b0e88817",shape="hexagon",style="filled",color="green" ]; -"359E" [ label="e5",shape="box",style="filled",color="grey" ]; -"88" [ label="503737b64d432c60d6ac557e0e6",shape="hexagon",style="filled",color="green" ]; -"361E" [ label="9937ccba1469",shape="box",style="filled",color="grey" ]; -"89" [ label="b36e0be6f67fc25286127456",shape="hexagon",style="filled",color="green" ]; -"363E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; -"90" [ label="4cc20a0b7651e486",shape="hexagon",style="filled",color="green" ]; -"365E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; -"91" [ label="08dade990b2282",shape="hexagon",style="filled",color="green" ]; -"367E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; -"92" [ label="f8128d574c356631b8a9",shape="hexagon",style="filled",color="green" ]; -"369E" [ label="",shape="box",style="filled",color="grey" ]; -"93" [ label="88a4f0337c2189c3fc7b31",shape="hexagon",style="filled",color="green" ]; -"729E" [ label="da0d7bbcf30",shape="box",style="filled",color="grey" ]; -"94" [ label="1b13908a9f0763c0ae54af9062080",shape="hexagon",style="filled",color="green" ]; -"371E" [ label="8b06a67a",shape="box",style="filled",color="grey" ]; -"95" [ label="e2a5d11499b7e",shape="hexagon",style="filled",color="green" ]; -"373E" [ label="66abc181ac4",shape="box",style="filled",color="grey" ]; -"96" [ label="90cc275011c2013c61eb11",shape="hexagon",style="filled",color="green" ]; -"375E" [ label="",shape="box",style="filled",color="grey" ]; -"97" [ label="1e003bfe8fc840df0163f4c",shape="hexagon",style="filled",color="green" ]; -"747E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"98" [ label="1927c743a0d440a5a0",shape="hexagon",style="filled",color="green" ]; -"377E" [ label="b12441ecff15fa12c",shape="box",style="filled",color="grey" ]; -"99" [ label="155d892827c33ed3cae3",shape="hexagon",style="filled",color="green" ]; -"379E" [ label="71e6b",shape="box",style="filled",color="grey" ]; -"100" [ label="9f24ba80192c339a64c0",shape="hexagon",style="filled",color="green" ]; -"381E" [ label="",shape="box",style="filled",color="grey" ]; -"101" [ label="3e814305b42beb41b8c706",shape="hexagon",style="filled",color="green" ]; -"383E" [ label="1c08373",shape="box",style="filled",color="grey" ]; -"102" [ label="eccfe5ff0af70fe9fbec8b2360f90",shape="hexagon",style="filled",color="green" ]; -"385E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; -"103" [ label="8fa622d9f842c5572a545ed72982",shape="hexagon",style="filled",color="green" ]; -"387E" [ label="4dccb",shape="box",style="filled",color="grey" ]; -"104" [ label="ad9142a65f5eab78b4ca5e",shape="hexagon",style="filled",color="green" ]; -"389E" [ label="f36cce089",shape="box",style="filled",color="grey" ]; -"105" [ label="20f234fdcd0e1fc50261ce8",shape="hexagon",style="filled",color="green" ]; -"391E" [ label="67219ef689f0146b544",shape="box",style="filled",color="grey" ]; -"106" [ label="e06cc38155ff6781cf944d745",shape="hexagon",style="filled",color="green" ]; -"393E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; -"107" [ label="cfdf1932665dcb4cd3c",shape="hexagon",style="filled",color="green" ]; -"395E" [ label="964b86fc1bba0e",shape="box",style="filled",color="grey" ]; -"108" [ label="6d4a4a5a5af91b895272c30",shape="hexagon",style="filled",color="green" ]; -"397E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; -"109" [ label="e0ad365c2fb444358201",shape="hexagon",style="filled",color="green" ]; -"399E" [ label="bb5e89c8963",shape="box",style="filled",color="grey" ]; -"110" [ label="b07bbdc8cca5985d4c4",shape="hexagon",style="filled",color="green" ]; -"401E" [ label="50023f6f88",shape="box",style="filled",color="grey" ]; -"111" [ label="df5dba74c75b228de48c",shape="hexagon",style="filled",color="green" ]; -"403E" [ label="7e493ee44b28",shape="box",style="filled",color="grey" ]; -"112" [ label="0b8694c9ef9b27b9c3d8",shape="hexagon",style="filled",color="green" ]; -"405E" [ label="2342b759c03",shape="box",style="filled",color="grey" ]; -"113" [ label="81e20155999fa64e0ae6fd",shape="hexagon",style="filled",color="green" ]; -"407E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; -"114" [ label="3ef07ae75d29a707",shape="hexagon",style="filled",color="green" ]; -"409E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; -"115" [ label="4a36db80f1ab1e97",shape="hexagon",style="filled",color="green" ]; -"411E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; -"116" [ label="16da5f1301b36df4df0f",shape="hexagon",style="filled",color="green" ]; -"413E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; -"117" [ label="6b3f3fa236bb90592d23a",shape="hexagon",style="filled",color="green" ]; -"415E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; -"118" [ label="f2a57e4d4f0cec516891e3",shape="hexagon",style="filled",color="green" ]; -"417E" [ label="bd2484",shape="box",style="filled",color="grey" ]; -"119" [ label="deb3089920548bf1ecb23f0d",shape="hexagon",style="filled",color="green" ]; -"419E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; -"120" [ label="bf01c8a262",shape="hexagon",style="filled",color="green" ]; -"421E" [ label="01",shape="box",style="filled",color="grey" ]; -"121" [ label="23dc3a52fed9c119610b5e8",shape="hexagon",style="filled",color="green" ]; -"423E" [ label="71e6b",shape="box",style="filled",color="grey" ]; -"122" [ label="aff7fc220edc93572bb2",shape="hexagon",style="filled",color="green" ]; -"748E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; -"123" [ label="78cc16f965adc5f712ea2372c6",shape="hexagon",style="filled",color="green" ]; -"425E" [ label="23ad1",shape="box",style="filled",color="grey" ]; -"124" [ label="5be631dff7b97697be7dc0a2f07f2",shape="hexagon",style="filled",color="green" ]; -"427E" [ label="",shape="box",style="filled",color="grey" ]; -"786E" [ label="421",shape="box",style="filled",color="grey" ]; -"125" [ label="48398d080dfcccced48da1980",shape="hexagon",style="filled",color="green" ]; -"431E" [ label="866808df",shape="box",style="filled",color="grey" ]; -"126" [ label="03716a2c341e5edaa31",shape="hexagon",style="filled",color="green" ]; -"433E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; -"127" [ label="ddfeabe456a9de5f5784",shape="hexagon",style="filled",color="green" ]; -"435E" [ label="aac615ae78",shape="box",style="filled",color="grey" ]; -"128" [ label="d550a7f392c787661aadd48",shape="hexagon",style="filled",color="green" ]; -"437E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; -"129" [ label="4c82921f4ad3f07066540",shape="hexagon",style="filled",color="green" ]; -"439E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; -"130" [ label="0bc7f8f513e0e74b270",shape="hexagon",style="filled",color="green" ]; -"441E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; -"131" [ label="3b1563a23eb9",shape="hexagon",style="filled",color="green" ]; -"443E" [ label="a8e9",shape="box",style="filled",color="grey" ]; -"132" [ label="be233fafa38d931d894",shape="hexagon",style="filled",color="green" ]; -"445E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; -"133" [ label="f906dc5244ee6a371f8",shape="hexagon",style="filled",color="green" ]; -"749E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; -"134" [ label="e7a887d88c2318beba51",shape="hexagon",style="filled",color="green" ]; -"447E" [ label="9d8988c0945d6",shape="box",style="filled",color="grey" ]; -"135" [ label="be6b73bd46a7a5183e8c91a",shape="hexagon",style="filled",color="green" ]; -"449E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; -"769E" [ label="444189d179b5db71fe",shape="box",style="filled",color="grey" ]; -"770E" [ label="1e1fbbe14ac24e0518",shape="box",style="filled",color="grey" ]; -"136" [ label="644f112bb0aa452ee7040a",shape="hexagon",style="filled",color="green" ]; -"451E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; -"137" [ label="010957669f3770aac",shape="hexagon",style="filled",color="green" ]; -"453E" [ label="78",shape="box",style="filled",color="grey" ]; -"138" [ label="0a185946ee443342b07d8e1",shape="hexagon",style="filled",color="green" ]; -"455E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; -"139" [ label="f66fe4df3d189e69ce10c9c",shape="hexagon",style="filled",color="green" ]; -"457E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; -"140" [ label="247e407f45b353f8",shape="hexagon",style="filled",color="green" ]; -"459E" [ label="",shape="box",style="filled",color="grey" ]; -"141" [ label="84907547f36d0ff7",shape="hexagon",style="filled",color="green" ]; -"461E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; -"142" [ label="805004328dad9d315d",shape="hexagon",style="filled",color="green" ]; -"463E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; -"143" [ label="4f0cbd3fbf0cb1e8c",shape="hexagon",style="filled",color="green" ]; -"465E" [ label="403126",shape="box",style="filled",color="grey" ]; -"144" [ label="4869e993f2bb10f",shape="hexagon",style="filled",color="green" ]; -"467E" [ label="ff",shape="box",style="filled",color="grey" ]; -"145" [ label="665b76844ff78fc2cf66ca2",shape="hexagon",style="filled",color="green" ]; -"469E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; -"146" [ label="3f16509139c7dad5163b91799",shape="hexagon",style="filled",color="green" ]; -"471E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; -"147" [ label="01db23a60422ba93a68611cc0",shape="hexagon",style="filled",color="green" ]; -"473E" [ label="",shape="box",style="filled",color="grey" ]; -"148" [ label="46125fcc583c0f494a3a1d3",shape="hexagon",style="filled",color="green" ]; -"475E" [ label="db6c4213a717bc",shape="box",style="filled",color="grey" ]; -"149" [ label="731857fe189fb398e80a0594",shape="hexagon",style="filled",color="green" ]; -"477E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; -"150" [ label="6fb7a84e370ef70feac5cb",shape="hexagon",style="filled",color="green" ]; -"479E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; -"151" [ label="e343cea291b79a2ed4e",shape="hexagon",style="filled",color="green" ]; -"481E" [ label="88d8b220746882d",shape="box",style="filled",color="grey" ]; -"152" [ label="5f2592b20f13356b7fc8b42",shape="hexagon",style="filled",color="green" ]; -"483E" [ label="",shape="box",style="filled",color="grey" ]; -"153" [ label="275a0407e33e9b8aa9cdd051",shape="hexagon",style="filled",color="green" ]; -"731E" [ label="",shape="box",style="filled",color="grey" ]; -"154" [ label="011d119375cf494ca2fa8d59",shape="hexagon",style="filled",color="green" ]; -"750E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"155" [ label="173fd00917644f0f1f3e3",shape="hexagon",style="filled",color="green" ]; -"485E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; -"156" [ label="c72df69b40156a3254",shape="hexagon",style="filled",color="green" ]; -"487E" [ label="fff03efcd",shape="box",style="filled",color="grey" ]; -"157" [ label="6c632ad9c42228bb337",shape="hexagon",style="filled",color="green" ]; -"489E" [ label="eb8",shape="box",style="filled",color="grey" ]; -"158" [ label="bbb13dc62adf2de2a42b6",shape="hexagon",style="filled",color="green" ]; -"491E" [ label="69ce90c9b2",shape="box",style="filled",color="grey" ]; -"159" [ label="6282bc21f6",shape="hexagon",style="filled",color="green" ]; -"495E" [ label="de34214b4c258c9333ec3",shape="box",style="filled",color="grey" ]; -"160" [ label="71cf45dd4e91bcca945137b40e",shape="hexagon",style="filled",color="green" ]; -"499E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; -"161" [ label="a3b6df27179b175c88fa4c9cf9f",shape="hexagon",style="filled",color="green" ]; -"501E" [ label="6577",shape="box",style="filled",color="grey" ]; -"162" [ label="284f14a259991806654e74",shape="hexagon",style="filled",color="green" ]; -"503E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; -"163" [ label="a7c99ccf6ddf6f5ebbe",shape="hexagon",style="filled",color="green" ]; -"505E" [ label="c4fd8",shape="box",style="filled",color="grey" ]; -"164" [ label="c32d2697e8",shape="hexagon",style="filled",color="green" ]; -"507E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; -"165" [ label="d12bd75c24b110ef90cdd35d3",shape="hexagon",style="filled",color="green" ]; -"509E" [ label="0668",shape="box",style="filled",color="grey" ]; -"166" [ label="1c07453d584f3d14b1876fdb",shape="hexagon",style="filled",color="green" ]; -"511E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; -"167" [ label="f713a8b311ffa05ce3683ad10",shape="hexagon",style="filled",color="green" ]; -"513E" [ label="30d6138b63eb",shape="box",style="filled",color="grey" ]; -"168" [ label="3cdc90c57243373efaba65a",shape="hexagon",style="filled",color="green" ]; -"515E" [ label="fa2afbd869",shape="box",style="filled",color="grey" ]; -"169" [ label="e3bdbca0e2256fffa8a59018",shape="hexagon",style="filled",color="green" ]; -"517E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"170" [ label="75ba8d840070942eb4e737849",shape="hexagon",style="filled",color="green" ]; -"519E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"171" [ label="fbdc3ca37406f66635c8b226e",shape="hexagon",style="filled",color="green" ]; -"521E" [ label="8cbcf5cb5",shape="box",style="filled",color="grey" ]; -"172" [ label="40b49a5a9bb256c7a3286e56",shape="hexagon",style="filled",color="green" ]; -"523E" [ label="f72564578be",shape="box",style="filled",color="grey" ]; -"173" [ label="3b2f08d52e4bca3f9ca7bbbd6",shape="hexagon",style="filled",color="green" ]; -"525E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"174" [ label="4a38abc630c82b0c48dfbf5271",shape="hexagon",style="filled",color="green" ]; -"527E" [ label="f0bd1521",shape="box",style="filled",color="grey" ]; -"175" [ label="2d7b7fb6c9ad6821752651f7",shape="hexagon",style="filled",color="green" ]; -"529E" [ label="47b2da3d",shape="box",style="filled",color="grey" ]; -"176" [ label="910b00285f11bb90d0a15641",shape="hexagon",style="filled",color="green" ]; -"531E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"177" [ label="24431c3eb075102f07cc2c1be",shape="hexagon",style="filled",color="green" ]; -"533E" [ label="",shape="box",style="filled",color="grey" ]; -"178" [ label="07f8a9e55a16beddb3c9153b0",shape="hexagon",style="filled",color="green" ]; -"535E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; -"179" [ label="c1c30f30d40c4f1f84924622f",shape="hexagon",style="filled",color="green" ]; -"537E" [ label="c5d5be3942",shape="box",style="filled",color="grey" ]; -"180" [ label="86276bb1e23f2c7ffcbe82a0",shape="hexagon",style="filled",color="green" ]; -"539E" [ label="0f940646",shape="box",style="filled",color="grey" ]; -"181" [ label="f78e145a127014eb43345a0c",shape="hexagon",style="filled",color="green" ]; -"541E" [ label="d370c12dbc",shape="box",style="filled",color="grey" ]; -"182" [ label="a27037332d9fa5c43bcfe94c0",shape="hexagon",style="filled",color="green" ]; -"543E" [ label="80874aa8",shape="box",style="filled",color="grey" ]; -"183" [ label="c29ce10bb8d19b498355aa04",shape="hexagon",style="filled",color="green" ]; -"545E" [ label="1c08373",shape="box",style="filled",color="grey" ]; -"184" [ label="4f8c642b53c349c687534bda35db",shape="hexagon",style="filled",color="green" ]; -"547E" [ label="46969c4",shape="box",style="filled",color="grey" ]; -"185" [ label="30cc206b1878485",shape="hexagon",style="filled",color="green" ]; -"549E" [ label="23ad1",shape="box",style="filled",color="grey" ]; -"186" [ label="5d69639a5e3bdd3d",shape="hexagon",style="filled",color="green" ]; -"551E" [ label="6139fa6adc88d",shape="box",style="filled",color="grey" ]; -"187" [ label="b656f0ed2202b8e46eb",shape="hexagon",style="filled",color="green" ]; -"553E" [ label="f6e6236b48bc3",shape="box",style="filled",color="grey" ]; -"188" [ label="3b566eaa70ed401479d43a9",shape="hexagon",style="filled",color="green" ]; -"555E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; -"189" [ label="d6125ef42bd9958",shape="hexagon",style="filled",color="green" ]; -"557E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; -"190" [ label="dd12f26f8d9bb55",shape="hexagon",style="filled",color="green" ]; -"559E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; -"191" [ label="ea890ccca2f7c2107351",shape="hexagon",style="filled",color="green" ]; -"561E" [ label="eb8",shape="box",style="filled",color="grey" ]; -"192" [ label="84e4f1c582427a98d7b",shape="hexagon",style="filled",color="green" ]; -"563E" [ label="eb8",shape="box",style="filled",color="grey" ]; -"193" [ label="d378760b814eaecb6efe636e0efc4",shape="hexagon",style="filled",color="green" ]; -"565E" [ label="81bcc35f82891",shape="box",style="filled",color="grey" ]; -"194" [ label="f722890f70a32dce3baff371a",shape="hexagon",style="filled",color="green" ]; -"567E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; -"195" [ label="666f11bb45c3a8dcf26e1ed79",shape="hexagon",style="filled",color="green" ]; -"569E" [ label="c90f755c8b6612d",shape="box",style="filled",color="grey" ]; -"196" [ label="91ecbe29a71f00ed5a3",shape="hexagon",style="filled",color="green" ]; -"571E" [ label="0a963fef9",shape="box",style="filled",color="grey" ]; -"197" [ label="30c3f3bf8463d3843dc57d8e98",shape="hexagon",style="filled",color="green" ]; -"573E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; -"198" [ label="8ea965ab6ee8dedb6c3333e9",shape="hexagon",style="filled",color="green" ]; -"575E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; -"199" [ label="3eecb304bab2136a76deda",shape="hexagon",style="filled",color="green" ]; -"577E" [ label="8df",shape="box",style="filled",color="grey" ]; -"200" [ label="d886e4b76537a99bc71b8a9331c94",shape="hexagon",style="filled",color="green" ]; -"579E" [ label="1172dca23",shape="box",style="filled",color="grey" ]; -"201" [ label="dcc5d5e9d6c4e",shape="hexagon",style="filled",color="green" ]; -"581E" [ label="a8e9",shape="box",style="filled",color="grey" ]; -"202" [ label="8292af691429f8d9ed481ff71ffd",shape="hexagon",style="filled",color="green" ]; -"583E" [ label="212af4",shape="box",style="filled",color="grey" ]; -"203" [ label="12fcb26b3de00ef98719c2ca",shape="hexagon",style="filled",color="green" ]; -"585E" [ label="",shape="box",style="filled",color="grey" ]; -"204" [ label="a141a557a60912051f3c135",shape="hexagon",style="filled",color="green" ]; -"587E" [ label="",shape="box",style="filled",color="grey" ]; -"205" [ label="64eeeddfc34489ff396",shape="hexagon",style="filled",color="green" ]; -"751E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"206" [ label="f5d636e14a6cd716362158d",shape="hexagon",style="filled",color="green" ]; -"589E" [ label="32c958c9997",shape="box",style="filled",color="grey" ]; -"207" [ label="84e4978afc069d5a1aecbf2b",shape="hexagon",style="filled",color="green" ]; -"593E" [ label="56caa96d171a9ac2da7c",shape="box",style="filled",color="grey" ]; -"208" [ label="52a6c2063bccd83110c32",shape="hexagon",style="filled",color="green" ]; -"597E" [ label="",shape="box",style="filled",color="grey" ]; -"209" [ label="46f754ea06f070dbc023e571a876",shape="hexagon",style="filled",color="green" ]; -"599E" [ label="ffccaa9e3",shape="box",style="filled",color="grey" ]; -"210" [ label="c10cb9baf4dcb43e24",shape="hexagon",style="filled",color="green" ]; -"601E" [ label="ac6e99186",shape="box",style="filled",color="grey" ]; -"211" [ label="3dafe1619016463f521f",shape="hexagon",style="filled",color="green" ]; -"603E" [ label="b9",shape="box",style="filled",color="grey" ]; -"212" [ label="0f5db6ce12751ddcc64e",shape="hexagon",style="filled",color="green" ]; -"605E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; -"213" [ label="34c8c8dc0f6e41c7e7b2",shape="hexagon",style="filled",color="green" ]; -"607E" [ label="2832ed5cea6",shape="box",style="filled",color="grey" ]; -"214" [ label="0a49c95f107c0aa57c9b5748",shape="hexagon",style="filled",color="green" ]; -"609E" [ label="",shape="box",style="filled",color="grey" ]; -"215" [ label="3b4fdad8e0429d112",shape="hexagon",style="filled",color="green" ]; -"611E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"216" [ label="17dafa5ebaafd48440e3",shape="hexagon",style="filled",color="green" ]; -"613E" [ label="b5f038f79a3",shape="box",style="filled",color="grey" ]; -"217" [ label="f4c69e5e212f89348122e8",shape="hexagon",style="filled",color="green" ]; -"615E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; -"218" [ label="4f2e020854dfacce46a12",shape="hexagon",style="filled",color="green" ]; -"617E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; -"219" [ label="6448451ac2ceade90715378b",shape="hexagon",style="filled",color="green" ]; -"619E" [ label="",shape="box",style="filled",color="grey" ]; -"220" [ label="7d7b14baa649330",shape="hexagon",style="filled",color="green" ]; -"621E" [ label="77d145b32328880440c7a",shape="box",style="filled",color="grey" ]; -"221" [ label="d7c27cc6f7b02a31eb64d",shape="hexagon",style="filled",color="green" ]; -"623E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; -"222" [ label="8f5a69ece1",shape="hexagon",style="filled",color="green" ]; -"752E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; -"223" [ label="eccf7c722ddf",shape="hexagon",style="filled",color="green" ]; -"625E" [ label="df61d5f5fc",shape="box",style="filled",color="grey" ]; -"224" [ label="86633c26be93ada8b",shape="hexagon",style="filled",color="green" ]; -"627E" [ label="08500a6044",shape="box",style="filled",color="grey" ]; -"225" [ label="3f9ddf1ffbc0d38b",shape="hexagon",style="filled",color="green" ]; -"629E" [ label="07",shape="box",style="filled",color="grey" ]; -"226" [ label="e33792703",shape="hexagon",style="filled",color="green" ]; -"631E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; -"227" [ label="293a225dc56dd1e0564e6bb",shape="hexagon",style="filled",color="green" ]; -"633E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; -"228" [ label="57c77c341f94afddef07e6",shape="hexagon",style="filled",color="green" ]; -"635E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; -"229" [ label="3bbfc7bfdbbb1ba1bfad7517",shape="hexagon",style="filled",color="green" ]; -"637E" [ label="",shape="box",style="filled",color="grey" ]; -"230" [ label="a7167d5eb5408b3839903",shape="hexagon",style="filled",color="green" ]; -"639E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; -"231" [ label="34d7bb6af4fcd8d630de72500c8",shape="hexagon",style="filled",color="green" ]; -"641E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; -"232" [ label="8e69341faa4489",shape="hexagon",style="filled",color="green" ]; -"643E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"233" [ label="459236f07c73814faf5",shape="hexagon",style="filled",color="green" ]; -"645E" [ label="18083a711d",shape="box",style="filled",color="grey" ]; -"234" [ label="c71aa521578164debd0c5",shape="hexagon",style="filled",color="green" ]; -"647E" [ label="78",shape="box",style="filled",color="grey" ]; -"235" [ label="a5520019b8a73bc141b5fd416a",shape="hexagon",style="filled",color="green" ]; -"649E" [ label="3219b6b71443",shape="box",style="filled",color="grey" ]; -"236" [ label="6c89dc59ee7aaebbbd6bb64",shape="hexagon",style="filled",color="green" ]; -"651E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; -"237" [ label="a9a36ef02f",shape="hexagon",style="filled",color="green" ]; -"653E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; -"238" [ label="3db761b596844f133c",shape="hexagon",style="filled",color="green" ]; -"655E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; -"239" [ label="383db224d7508ef072bea21d0",shape="hexagon",style="filled",color="green" ]; -"657E" [ label="975fedfb64df",shape="box",style="filled",color="grey" ]; -"240" [ label="8e307415fb435445ced7",shape="hexagon",style="filled",color="green" ]; -"659E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; -"241" [ label="aff6d7896e0e142bbc3e78",shape="hexagon",style="filled",color="green" ]; -"661E" [ label="d2498",shape="box",style="filled",color="grey" ]; -"242" [ label="e153c6e676c7369b285b4e9033a",shape="hexagon",style="filled",color="green" ]; -"663E" [ label="",shape="box",style="filled",color="grey" ]; -"243" [ label="f3c4311de0e931f08c232b",shape="hexagon",style="filled",color="green" ]; -"665E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; -"244" [ label="0c72a426929600000f5",shape="hexagon",style="filled",color="green" ]; -"667E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; -"245" [ label="38fa61352f5086d2cb51",shape="hexagon",style="filled",color="green" ]; -"669E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; -"246" [ label="ad1dd724f1c3e",shape="hexagon",style="filled",color="green" ]; -"671E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; -"247" [ label="11bb8ed3ae227d3acefc",shape="hexagon",style="filled",color="green" ]; -"673E" [ label="eb8",shape="box",style="filled",color="grey" ]; -"248" [ label="f2c7b3bb4d44f977d0ab8a42351",shape="hexagon",style="filled",color="green" ]; -"675E" [ label="",shape="box",style="filled",color="grey" ]; -"249" [ label="51e045ca826077ae765",shape="hexagon",style="filled",color="green" ]; -"679E" [ label="e842",shape="box",style="filled",color="grey" ]; -"250" [ label="aa0adc8978020629574",shape="hexagon",style="filled",color="green" ]; -"753E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; -"251" [ label="3b6b2c549de670d7bf5fc0ee",shape="hexagon",style="filled",color="green" ]; -"681E" [ label="",shape="box",style="filled",color="grey" ]; -"252" [ label="5eea496cc301b2a9721",shape="hexagon",style="filled",color="green" ]; -"683E" [ label="",shape="box",style="filled",color="grey" ]; -"253" [ label="bfc6564cbdeeffac00a141",shape="hexagon",style="filled",color="green" ]; -"685E" [ label="3b0a8a1c2e5050bd",shape="box",style="filled",color="grey" ]; -"254" [ label="c360aaeb167487c9578a8f",shape="hexagon",style="filled",color="green" ]; -"687E" [ label="d",shape="box",style="filled",color="grey" ]; -"255" [ label="39d025b265f9790490781cb201",shape="hexagon",style="filled",color="green" ]; -"689E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; -"256" [ label="b4ce21e0a3df1d097277d6",shape="hexagon",style="filled",color="green" ]; -"691E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; -"257" [ label="8bdb6a91c6dee925b557c705b3",shape="hexagon",style="filled",color="green" ]; -"693E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; -"258" [ label="ac487676a04e4",shape="hexagon",style="filled",color="green" ]; -"695E" [ label="a8e9",shape="box",style="filled",color="grey" ]; -"259" [ label="18115fa32ff1cb99",shape="hexagon",style="filled",color="green" ]; -"697E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; -"260" [ label="b7b899dc8bc6a32b28cb098fa16",shape="hexagon",style="filled",color="green" ]; -"699E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; -"261" [ label="b69e426d974e1907e88",shape="hexagon",style="filled",color="green" ]; -"703E" [ label="e842",shape="box",style="filled",color="grey" ]; -"262" [ label="60d0128bdb61ae40e98638bd1391",shape="hexagon",style="filled",color="green" ]; -"705E" [ label="23ad1",shape="box",style="filled",color="grey" ]; -"264" [ label="8fb60d769e4c387",shape="hexagon",style="filled",color="green" ]; -"709E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; -"265" [ label="e1fa7f549e5a0893bb42da5",shape="hexagon",style="filled",color="green" ]; -"711E" [ label="6a3c6921b0aeceda3",shape="box",style="filled",color="grey" ]; -"266" [ label="a77622f2ff77ffeeb2",shape="hexagon",style="filled",color="green" ]; -"713E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; -"267" [ label="30d9d350943c0e3ff7594b50",shape="hexagon",style="filled",color="green" ]; -"715E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; -"268" [ label="89ced1a7906d58d687d5a04",shape="hexagon",style="filled",color="green" ]; -"717E" [ label="c0174bbe7ae8",shape="box",style="filled",color="grey" ]; -"269" [ label="1de26f6b12b0d292f94184",shape="hexagon",style="filled",color="green" ]; -"719E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; -"270" [ label="26fa7360ab81be9d4434a",shape="hexagon",style="filled",color="green" ]; -"721E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; -"272" [ label="4a9d79c960b8d33e39251e5f66",shape="hexagon" ]; -"34E" [ label="330342f283ef2",shape="box",style="filled",color="grey" ]; -"252E" [ label="3dafb9a29c00",shape="box",style="filled",color="grey" ]; -"436E" [ label="8d5137b16a",shape="box",style="filled",color="grey" ]; -"274" [ label="10a7d61c201c67a5e78542807cd",shape="hexagon" ]; -"59E" [ label="ef6361295eba07",shape="box",style="filled",color="grey" ]; -"500E" [ label="a8f0fe2eb7bc1471",shape="box",style="filled",color="grey" ]; -"720E" [ label="cfff3acd8e9d",shape="box",style="filled",color="grey" ]; -"275" [ label="f8ff39eab120851f143bf19",shape="hexagon" ]; -"98E" [ label="4e3cfd27a",shape="box",style="filled",color="grey" ]; -"278" [ label="4995c71223c9f6067324d387a2",shape="hexagon" ]; -"35E" [ label="57948adb5dead",shape="box",style="filled",color="grey" ]; -"488E" [ label="a738ba39",shape="box",style="filled",color="grey" ]; -"598E" [ label="be7d637c50c",shape="box",style="filled",color="grey" ]; -"604E" [ label="8d52f183ec",shape="box",style="filled",color="grey" ]; -"628E" [ label="cef12b6",shape="box",style="filled",color="grey" ]; -"279" [ label="b9ae94e6935503603341ecf4",shape="hexagon" ]; -"99E" [ label="14a3c17f3d",shape="box",style="filled",color="grey" ]; -"280" [ label="fd28c194a46fde909b019c52f",shape="hexagon" ]; -"242E" [ label="9fe65061641",shape="box",style="filled",color="grey" ]; -"270E" [ label="34d06d1ed6",shape="box",style="filled",color="grey" ]; -"272E" [ label="713db1c1",shape="box",style="filled",color="grey" ]; -"284E" [ label="90dccb18c0",shape="box",style="filled",color="grey" ]; -"286E" [ label="e17fea65",shape="box",style="filled",color="grey" ]; -"288E" [ label="aebb7b91b",shape="box",style="filled",color="grey" ]; -"586E" [ label="4348f3abcb7716",shape="box",style="filled",color="grey" ]; -"763E" [ label="b082f7a5ff",shape="box",style="filled",color="grey" ]; -"281" [ label="7c0ab977f5a3c4ab6d625f5033",shape="hexagon" ]; -"45E" [ label="20949455f573f",shape="box",style="filled",color="grey" ]; -"470E" [ label="c338481d79773",shape="box",style="filled",color="grey" ]; -"670E" [ label="e1d01ef89f",shape="box",style="filled",color="grey" ]; -"722E" [ label="c4507c22d19",shape="box",style="filled",color="grey" ]; -"282" [ label="7e0b91491c8c8566892cd9a0889",shape="hexagon" ]; -"103E" [ label="de9efa12873949",shape="box",style="filled",color="grey" ]; -"283" [ label="d58478d9c273ad4f4b2e091324",shape="hexagon" ]; -"165E" [ label="1a220eb692c",shape="box",style="filled",color="grey" ]; -"284" [ label="8be0efdd94a6383e87fbfded4f",shape="hexagon" ]; -"39E" [ label="c8a6c26d4fd9f",shape="box",style="filled",color="grey" ]; -"224E" [ label="8cbae42a3900",shape="box",style="filled",color="grey" ]; -"268E" [ label="fc73",shape="box",style="filled",color="grey" ]; -"632E" [ label="",shape="box",style="filled",color="grey" ]; -"710E" [ label="102f1",shape="box",style="filled",color="grey" ]; -"285" [ label="3aeb78ea51020a44f2d2615436dae",shape="hexagon" ]; -"53E" [ label="96deede0c6b44119",shape="box",style="filled",color="grey" ]; -"286" [ label="6bbd5b422edb8e358dcc20eecf9",shape="hexagon" ]; -"38E" [ label="4f2de229621272",shape="box",style="filled",color="grey" ]; -"166E" [ label="d495de0b35f6",shape="box",style="filled",color="grey" ]; -"288" [ label="4856000a6802ddfc121ef40432297",shape="hexagon",style="filled",color="#ff0000" ]; -"40E" [ label="04904a458422a5b9",shape="box",style="filled",color="grey" ]; -"218E" [ label="8cd4d",shape="box",style="filled",color="grey" ]; -"244E" [ label="",shape="box",style="filled",color="grey" ]; -"246E" [ label="9be88247",shape="box",style="filled",color="grey" ]; -"258E" [ label="4f05b",shape="box",style="filled",color="grey" ]; -"290E" [ label="8b092",shape="box",style="filled",color="grey" ]; -"292E" [ label="c3bbf4",shape="box",style="filled",color="grey" ]; -"308E" [ label="6331b3f",shape="box",style="filled",color="grey" ]; -"318E" [ label="",shape="box",style="filled",color="grey" ]; -"388E" [ label="3711",shape="box",style="filled",color="grey" ]; -"472E" [ label="c5255d",shape="box",style="filled",color="grey" ]; -"478E" [ label="5c6a2",shape="box",style="filled",color="grey" ]; -"566E" [ label="51ec95518d1b3",shape="box",style="filled",color="grey" ]; -"570E" [ label="82a65ed4b69",shape="box",style="filled",color="grey" ]; -"574E" [ label="05fed5e",shape="box",style="filled",color="grey" ]; -"608E" [ label="bf",shape="box",style="filled",color="grey" ]; -"614E" [ label="ce",shape="box",style="filled",color="grey" ]; -"658E" [ label="1a830d9f",shape="box",style="filled",color="grey" ]; -"664E" [ label="",shape="box",style="filled",color="grey" ]; -"682E" [ label="",shape="box",style="filled",color="grey" ]; -"289" [ label="2e31175cbd52fcd08360fe86d20",shape="hexagon" ]; -"41E" [ label="4ad5d68f07981a",shape="box",style="filled",color="grey" ]; -"636E" [ label="51192117f9b4",shape="box",style="filled",color="grey" ]; -"642E" [ label="6bf214d9e7fa5f2df",shape="box",style="filled",color="grey" ]; -"690E" [ label="558d8534f92fddfe",shape="box",style="filled",color="grey" ]; -"700E" [ label="6819fd5a6cdd280dd",shape="box",style="filled",color="grey" ]; -"290" [ label="3aa0ce5efcf79bc3ecced1886e89",shape="hexagon" ]; -"56E" [ label="ff9d64ddf49a20f",shape="box",style="filled",color="grey" ]; -"264E" [ label="6c93f24516f01d",shape="box",style="filled",color="grey" ]; -"510E" [ label="32b98f11f3d01d6",shape="box",style="filled",color="grey" ]; -"718E" [ label="8f7c875500073",shape="box",style="filled",color="grey" ]; -"291" [ label="7c1767485953d9c2",shape="hexagon" ]; -"66E" [ label="086",shape="box",style="filled",color="grey" ]; -"76E" [ label="",shape="box",style="filled",color="grey" ]; -"610E" [ label="450d3a2d49cbfd",shape="box",style="filled",color="grey" ]; -"292" [ label="9c1305d59c37e9be9f13d7d049c",shape="hexagon" ]; -"73E" [ label="817",shape="box",style="filled",color="grey" ]; -"293" [ label="efe092824916a5637ee35d439589",shape="hexagon" ]; -"49E" [ label="",shape="box",style="filled",color="grey" ]; -"214E" [ label="",shape="box",style="filled",color="grey" ]; -"216E" [ label="",shape="box",style="filled",color="grey" ]; -"236E" [ label="",shape="box",style="filled",color="grey" ]; -"278E" [ label="",shape="box",style="filled",color="grey" ]; -"358E" [ label="",shape="box",style="filled",color="grey" ]; -"398E" [ label="",shape="box",style="filled",color="grey" ]; -"400E" [ label="",shape="box",style="filled",color="grey" ]; -"402E" [ label="",shape="box",style="filled",color="grey" ]; -"404E" [ label="",shape="box",style="filled",color="grey" ]; -"406E" [ label="",shape="box",style="filled",color="grey" ]; -"408E" [ label="",shape="box",style="filled",color="grey" ]; -"412E" [ label="",shape="box",style="filled",color="grey" ]; -"438E" [ label="",shape="box",style="filled",color="grey" ]; -"448E" [ label="",shape="box",style="filled",color="grey" ]; -"476E" [ label="",shape="box",style="filled",color="grey" ]; -"504E" [ label="",shape="box",style="filled",color="grey" ]; -"552E" [ label="",shape="box",style="filled",color="grey" ]; -"634E" [ label="",shape="box",style="filled",color="grey" ]; -"768E" [ label="",shape="box",style="filled",color="grey" ]; -"295" [ label="70815f0352b43dc1562133ab6eb",shape="hexagon",style="filled",color="#A52A2A" ]; -"44E" [ label="ef2d4636934472",shape="box",style="filled",color="grey" ]; -"92E" [ label="22bd92e302816",shape="box",style="filled",color="grey" ]; -"250E" [ label="74e86",shape="box",style="filled",color="grey" ]; -"316E" [ label="",shape="box",style="filled",color="grey" ]; -"380E" [ label="",shape="box",style="filled",color="grey" ]; -"424E" [ label="c",shape="box",style="filled",color="grey" ]; -"442E" [ label="a5a",shape="box",style="filled",color="grey" ]; -"446E" [ label="bce",shape="box",style="filled",color="grey" ]; -"454E" [ label="",shape="box",style="filled",color="grey" ]; -"460E" [ label="",shape="box",style="filled",color="grey" ]; -"462E" [ label="",shape="box",style="filled",color="grey" ]; -"648E" [ label="",shape="box",style="filled",color="grey" ]; -"656E" [ label="e9",shape="box",style="filled",color="grey" ]; -"666E" [ label="b701e7",shape="box",style="filled",color="grey" ]; -"692E" [ label="f2e7cc",shape="box",style="filled",color="grey" ]; -"712E" [ label="8a9eb2806b0aa",shape="box",style="filled",color="grey" ]; -"296" [ label="e287d497450664a4c0f4efc338",shape="hexagon",style="filled",color="#ff0000" ]; -"47E" [ label="06eff1db45cdf",shape="box",style="filled",color="grey" ]; -"330E" [ label="c0f34a600",shape="box",style="filled",color="grey" ]; -"514E" [ label="bd7aca295ca",shape="box",style="filled",color="grey" ]; -"516E" [ label="0da9135",shape="box",style="filled",color="grey" ]; -"518E" [ label="fe821bce",shape="box",style="filled",color="grey" ]; -"520E" [ label="e64f22a31",shape="box",style="filled",color="grey" ]; -"522E" [ label="46e412a3",shape="box",style="filled",color="grey" ]; -"526E" [ label="99da1f8a5",shape="box",style="filled",color="grey" ]; -"528E" [ label="0f167280",shape="box",style="filled",color="grey" ]; -"530E" [ label="82d201",shape="box",style="filled",color="grey" ]; -"532E" [ label="1d529eb4",shape="box",style="filled",color="grey" ]; -"534E" [ label="",shape="box",style="filled",color="grey" ]; -"536E" [ label="bf141dbce",shape="box",style="filled",color="grey" ]; -"538E" [ label="e3fd0c7b3",shape="box",style="filled",color="grey" ]; -"540E" [ label="c96cb3",shape="box",style="filled",color="grey" ]; -"542E" [ label="0fabab47",shape="box",style="filled",color="grey" ]; -"544E" [ label="1b82200",shape="box",style="filled",color="grey" ]; -"297" [ label="2ced414a91575a48f2dd29a",shape="hexagon" ]; -"46E" [ label="85221d5e9e",shape="box",style="filled",color="grey" ]; -"93E" [ label="97a7eea3f",shape="box",style="filled",color="grey" ]; -"206E" [ label="4d22e1",shape="box",style="filled",color="grey" ]; -"426E" [ label="e65185ca",shape="box",style="filled",color="grey" ]; -"550E" [ label="",shape="box",style="filled",color="grey" ]; -"706E" [ label="a9012b7bb5",shape="box",style="filled",color="grey" ]; -"298" [ label="38f162cf917ce7298663a1f1c607",shape="hexagon" ]; -"36E" [ label="a031c9192ae8e75",shape="box",style="filled",color="grey" ]; -"95E" [ label="062fc905b9eb35",shape="box",style="filled",color="grey" ]; -"364E" [ label="c8fc17180bea86",shape="box",style="filled",color="grey" ]; -"394E" [ label="09e64744536c5e1",shape="box",style="filled",color="grey" ]; -"420E" [ label="af4a1fac3e2076",shape="box",style="filled",color="grey" ]; -"456E" [ label="238805e2194c3",shape="box",style="filled",color="grey" ]; -"624E" [ label="73e6ed83012",shape="box",style="filled",color="grey" ]; -"299" [ label="549fa15d68f0b3bee6192f888cd8",shape="hexagon" ]; -"48E" [ label="d17f8f4eeb8e63d",shape="box",style="filled",color="grey" ]; -"168E" [ label="cca7040e47789",shape="box",style="filled",color="grey" ]; -"260E" [ label="47ebc3f17",shape="box",style="filled",color="grey" ]; -"282E" [ label="cf5a6049ad",shape="box",style="filled",color="grey" ]; -"554E" [ label="2a47a6a27",shape="box",style="filled",color="grey" ]; -"590E" [ label="eff3468631dd4",shape="box",style="filled",color="grey" ]; -"767E" [ label="efb52b499303115c33fd",shape="box",style="filled",color="grey" ]; -"300" [ label="8593dcf973b110d00cecdc1e756",shape="hexagon",style="filled",color="#ff7f00" ]; -"62E" [ label="472a156cf2b55f",shape="box",style="filled",color="grey" ]; -"190E" [ label="647",shape="box",style="filled",color="grey" ]; -"226E" [ label="",shape="box",style="filled",color="grey" ]; -"238E" [ label="8a",shape="box",style="filled",color="grey" ]; -"254E" [ label="",shape="box",style="filled",color="grey" ]; -"256E" [ label="",shape="box",style="filled",color="grey" ]; -"262E" [ label="",shape="box",style="filled",color="grey" ]; -"266E" [ label="e8b",shape="box",style="filled",color="grey" ]; -"274E" [ label="",shape="box",style="filled",color="grey" ]; -"276E" [ label="f",shape="box",style="filled",color="grey" ]; -"294E" [ label="",shape="box",style="filled",color="grey" ]; -"296E" [ label="",shape="box",style="filled",color="grey" ]; -"310E" [ label="1b34fb150",shape="box",style="filled",color="grey" ]; -"320E" [ label="",shape="box",style="filled",color="grey" ]; -"322E" [ label="a7d2",shape="box",style="filled",color="grey" ]; -"332E" [ label="",shape="box",style="filled",color="grey" ]; -"340E" [ label="",shape="box",style="filled",color="grey" ]; -"344E" [ label="f55670",shape="box",style="filled",color="grey" ]; -"346E" [ label="1ed67841",shape="box",style="filled",color="grey" ]; -"348E" [ label="07283",shape="box",style="filled",color="grey" ]; -"374E" [ label="73ba1714ee",shape="box",style="filled",color="grey" ]; -"378E" [ label="27709106",shape="box",style="filled",color="grey" ]; -"452E" [ label="93ea0",shape="box",style="filled",color="grey" ]; -"508E" [ label="",shape="box",style="filled",color="grey" ]; -"524E" [ label="1d792d81",shape="box",style="filled",color="grey" ]; -"612E" [ label="a",shape="box",style="filled",color="grey" ]; -"626E" [ label="",shape="box",style="filled",color="grey" ]; -"638E" [ label="",shape="box",style="filled",color="grey" ]; -"644E" [ label="",shape="box",style="filled",color="grey" ]; -"654E" [ label="",shape="box",style="filled",color="grey" ]; -"672E" [ label="",shape="box",style="filled",color="grey" ]; -"302" [ label="23f94655294d3ff537f2915fa",shape="hexagon" ]; -"797E" [ label="",shape="box",style="filled",color="grey" ]; -"798E" [ label="a2eab7c9fa641e5f",shape="box",style="filled",color="grey" ]; -"303" [ label="a9058241db5b6b6c25569acdf5",shape="hexagon" ]; -"52E" [ label="b2babf3244213",shape="box",style="filled",color="grey" ]; -"650E" [ label="b354cd9e9dbb0bfa",shape="box",style="filled",color="grey" ]; -"304" [ label="bdbdb31bd777fb65dd6dd2d0e7",shape="hexagon" ]; -"50E" [ label="3bec1c012b498",shape="box",style="filled",color="grey" ]; -"640E" [ label="c54f0fc1e05",shape="box",style="filled",color="grey" ]; -"646E" [ label="9ab6c66dc",shape="box",style="filled",color="grey" ]; -"652E" [ label="699e3db878047",shape="box",style="filled",color="grey" ]; -"306" [ label="1d4ea80c7194689d69f9592186",shape="hexagon" ]; -"55E" [ label="8066f87a88f4e",shape="box",style="filled",color="grey" ]; -"220E" [ label="3a8173d6c",shape="box",style="filled",color="grey" ]; -"338E" [ label="24dfe1a997a",shape="box",style="filled",color="grey" ]; -"368E" [ label="65a1",shape="box",style="filled",color="grey" ]; -"486E" [ label="59a8b435ccd",shape="box",style="filled",color="grey" ]; -"490E" [ label="86e9b0428",shape="box",style="filled",color="grey" ]; -"562E" [ label="5a7a610a8a",shape="box",style="filled",color="grey" ]; -"564E" [ label="8f143077e",shape="box",style="filled",color="grey" ]; -"600E" [ label="6472c2861e0e0dd681",shape="box",style="filled",color="grey" ]; -"668E" [ label="f0f45e707",shape="box",style="filled",color="grey" ]; -"674E" [ label="95e93c4a13",shape="box",style="filled",color="grey" ]; -"698E" [ label="33e1de",shape="box",style="filled",color="grey" ]; -"307" [ label="7204950f6233bf9c9e1f00d4a870",shape="hexagon" ]; -"107E" [ label="ccceeef40edda78",shape="box",style="filled",color="grey" ]; -"308" [ label="a2c4b1d72e2da483a86ae0c62e5",shape="hexagon" ]; -"108E" [ label="eedc819a68add6",shape="box",style="filled",color="grey" ]; -"309" [ label="f603819d560c5603259aa05dca",shape="hexagon" ]; -"109E" [ label="acacfc83af504",shape="box",style="filled",color="grey" ]; -"310" [ label="2f43cba12702078b4e0d3bfdae2bc",shape="hexagon" ]; -"110E" [ label="3c1edc8de4795936",shape="box",style="filled",color="grey" ]; -"311" [ label="8f9cdc26798117dd3e9ee4a8770",shape="hexagon" ]; -"58E" [ label="881d373",shape="box",style="filled",color="grey" ]; -"234E" [ label="",shape="box",style="filled",color="grey" ]; -"300E" [ label="",shape="box",style="filled",color="grey" ]; -"306E" [ label="8c7cd9b93b1cbe48e1",shape="box",style="filled",color="grey" ]; -"314E" [ label="616d8a7b",shape="box",style="filled",color="grey" ]; -"342E" [ label="",shape="box",style="filled",color="grey" ]; -"354E" [ label="",shape="box",style="filled",color="grey" ]; -"370E" [ label="",shape="box",style="filled",color="grey" ]; -"382E" [ label="",shape="box",style="filled",color="grey" ]; -"422E" [ label="",shape="box",style="filled",color="grey" ]; -"444E" [ label="",shape="box",style="filled",color="grey" ]; -"582E" [ label="",shape="box",style="filled",color="grey" ]; -"620E" [ label="",shape="box",style="filled",color="grey" ]; -"630E" [ label="",shape="box",style="filled",color="grey" ]; -"684E" [ label="",shape="box",style="filled",color="grey" ]; -"696E" [ label="",shape="box",style="filled",color="grey" ]; -"801E" [ label="",shape="box",style="filled",color="grey" ]; -"312" [ label="97c9d726e27304311901a52ce",shape="hexagon",style="filled",color="#ff0000" ]; -"42E" [ label="1112164c2f7a",shape="box",style="filled",color="grey" ]; -"192E" [ label="5c609b12c",shape="box",style="filled",color="grey" ]; -"194E" [ label="00265",shape="box",style="filled",color="grey" ]; -"196E" [ label="04767",shape="box",style="filled",color="grey" ]; -"198E" [ label="f0d99f16",shape="box",style="filled",color="grey" ]; -"200E" [ label="",shape="box",style="filled",color="grey" ]; -"202E" [ label="6e186b",shape="box",style="filled",color="grey" ]; -"204E" [ label="d382",shape="box",style="filled",color="grey" ]; -"312E" [ label="c6b5321a",shape="box",style="filled",color="grey" ]; -"336E" [ label="",shape="box",style="filled",color="grey" ]; -"376E" [ label="",shape="box",style="filled",color="grey" ]; -"384E" [ label="aeb8",shape="box",style="filled",color="grey" ]; -"386E" [ label="2e53009d4a375",shape="box",style="filled",color="grey" ]; -"428E" [ label="",shape="box",style="filled",color="grey" ]; -"474E" [ label="",shape="box",style="filled",color="grey" ]; -"484E" [ label="",shape="box",style="filled",color="grey" ]; -"546E" [ label="dea1d1",shape="box",style="filled",color="grey" ]; -"548E" [ label="5a0b4b906a",shape="box",style="filled",color="grey" ]; -"314" [ label="1727041c622518c9dd24f7c211",shape="hexagon" ]; -"113E" [ label="49704867bee95",shape="box",style="filled",color="grey" ]; -"315" [ label="31f2f9aef958979f9f3532b9b",shape="hexagon",style="filled",color="#ff0000" ]; -"43E" [ label="47cd70f",shape="box",style="filled",color="grey" ]; -"240E" [ label="248df40dae",shape="box",style="filled",color="grey" ]; -"298E" [ label="",shape="box",style="filled",color="grey" ]; -"334E" [ label="9dd5bf47f",shape="box",style="filled",color="grey" ]; -"360E" [ label="",shape="box",style="filled",color="grey" ]; -"390E" [ label="28533c",shape="box",style="filled",color="grey" ]; -"418E" [ label="",shape="box",style="filled",color="grey" ]; -"492E" [ label="a4c7d0",shape="box",style="filled",color="grey" ]; -"502E" [ label="4f6f7f",shape="box",style="filled",color="grey" ]; -"584E" [ label="7ab64a969",shape="box",style="filled",color="grey" ]; -"588E" [ label="",shape="box",style="filled",color="grey" ]; -"602E" [ label="69",shape="box",style="filled",color="grey" ]; -"606E" [ label="67513d",shape="box",style="filled",color="grey" ]; -"662E" [ label="cf",shape="box",style="filled",color="grey" ]; -"316" [ label="a54092a3033f7d5e41e0a76c1",shape="hexagon" ]; -"51E" [ label="1467f017b74e",shape="box",style="filled",color="grey" ]; -"317" [ label="2043b477ac0393676a4309514d0",shape="hexagon" ]; -"116E" [ label="bdec8c86db51b9",shape="box",style="filled",color="grey" ]; -"318" [ label="ab48d1f65812bc0f8ab6941c3b5",shape="hexagon" ]; -"74E" [ label="81",shape="box",style="filled",color="grey" ]; -"319" [ label="ca3d67754cf62fdafbf0a1e0",shape="hexagon" ]; -"57E" [ label="75b14f1719d",shape="box",style="filled",color="grey" ]; -"94E" [ label="62f36ea98a",shape="box",style="filled",color="grey" ]; -"350E" [ label="e3a76d31ca59a",shape="box",style="filled",color="grey" ]; -"440E" [ label="b3cadc253f7",shape="box",style="filled",color="grey" ]; -"466E" [ label="fb58e11",shape="box",style="filled",color="grey" ]; -"676E" [ label="8606837526d81cdec",shape="box",style="filled",color="grey" ]; -"320" [ label="a7a7f3681dad1250b01cf80bc17",shape="hexagon" ]; -"60E" [ label="2c514b0cd8f7d3",shape="box",style="filled",color="grey" ]; -"366E" [ label="7e494b",shape="box",style="filled",color="grey" ]; -"434E" [ label="15d44ab97",shape="box",style="filled",color="grey" ]; -"458E" [ label="78b2d75d00166",shape="box",style="filled",color="grey" ]; -"618E" [ label="761e0f72f95",shape="box",style="filled",color="grey" ]; -"321" [ label="275afb2b215b966d9fac51b96b9",shape="hexagon" ]; -"72E" [ label="ac284d73563",shape="box",style="filled",color="grey" ]; -"362E" [ label="7e74e1587f3a4d208",shape="box",style="filled",color="grey" ]; -"372E" [ label="ffd1b1af3b6864078f3",shape="box",style="filled",color="grey" ]; -"572E" [ label="b38049e00",shape="box",style="filled",color="grey" ]; -"322" [ label="c3c93c700edc0cb4f95f03c04",shape="hexagon" ]; -"54E" [ label="99237fce1358",shape="box",style="filled",color="grey" ]; -"222E" [ label="3dcf8f454",shape="box",style="filled",color="grey" ]; -"302E" [ label="c5acd20cad2",shape="box",style="filled",color="grey" ]; -"556E" [ label="6c998bf2a5edd",shape="box",style="filled",color="grey" ]; -"558E" [ label="4b683",shape="box",style="filled",color="grey" ]; -"323" [ label="63a3d4fb9d38a0182be6e39e76",shape="hexagon" ]; -"37E" [ label="bba6e6e194ccf",shape="box",style="filled",color="grey" ]; -"208E" [ label="01938827",shape="box",style="filled",color="grey" ]; -"210E" [ label="9",shape="box",style="filled",color="grey" ]; -"352E" [ label="64ef1d545",shape="box",style="filled",color="grey" ]; -"450E" [ label="b473716",shape="box",style="filled",color="grey" ]; -"568E" [ label="7c13bf753da",shape="box",style="filled",color="grey" ]; -"576E" [ label="4e4a79111d",shape="box",style="filled",color="grey" ]; -"686E" [ label="af4abb0d6a99",shape="box",style="filled",color="grey" ]; -"324" [ label="4399cf78123dedd0dfe9776104",shape="hexagon" ]; -"228E" [ label="af9c489df53",shape="box",style="filled",color="grey" ]; -"248E" [ label="3703059dbc5a8",shape="box",style="filled",color="grey" ]; -"304E" [ label="8a46e6",shape="box",style="filled",color="grey" ]; -"468E" [ label="f9d09",shape="box",style="filled",color="grey" ]; -"578E" [ label="cd1e9af3dec2",shape="box",style="filled",color="grey" ]; -"660E" [ label="9e650e89bb",shape="box",style="filled",color="grey" ]; -"688E" [ label="f62b136b2171",shape="box",style="filled",color="grey" ]; -"694E" [ label="4727c415d06bcbef",shape="box",style="filled",color="grey" ]; -"714E" [ label="38b3b0d9",shape="box",style="filled",color="grey" ]; -"766E" [ label="a153512d982",shape="box",style="filled",color="grey" ]; -"325" [ label="40f253cd228f7ac2d0aee",shape="hexagon" ]; -"97E" [ label="a3ff993",shape="box",style="filled",color="grey" ]; -"506E" [ label="7528dd86b",shape="box",style="filled",color="grey" ]; -"326" [ label="89a2505da6179a80202d4a6c3",shape="hexagon" ]; -"61E" [ label="75eea05672a5",shape="box",style="filled",color="grey" ]; -"175E" [ label="3b0c08dd2ca",shape="box",style="filled",color="grey" ]; -"482E" [ label="a3781072b",shape="box",style="filled",color="grey" ]; -"328" [ label="2601085bde1b2450d64509f36",shape="hexagon" ]; -"75E" [ label="0efbd",shape="box",style="filled",color="grey" ]; -"580E" [ label="bb92d1da1f38d52f8ff",shape="box",style="filled",color="grey" ]; -"329" [ label="5c81103c751345d0ee0f4bd",shape="hexagon" ]; -"96E" [ label="b23526044",shape="box",style="filled",color="grey" ]; -"330" [ label="fcbd9ad14139718bc6fcc8b4",shape="hexagon" ]; -"100E" [ label="73ca543bf1",shape="box",style="filled",color="grey" ]; -"170E" [ label="c2f32e2cf9",shape="box",style="filled",color="grey" ]; -"333" [ label="44cbb41a9cfc15497eacd294",color="yellow",style="filled",shape="doubleoctagon" ]; -"63E" [ label="6a91",shape="box",style="filled",color="grey" ]; -"67E" [ label="b074e",shape="box",style="filled",color="grey" ]; -"68E" [ label="06209",shape="box",style="filled",color="grey" ]; -"69E" [ label="58e3dcc618",shape="box",style="filled",color="grey" ]; -"70E" [ label="eee44624da",shape="box",style="filled",color="grey" ]; -"71E" [ label="6a91",shape="box",style="filled",color="grey" ]; -"802E" [ label="e1e8c",shape="box",style="filled",color="grey" ]; -"793E" [ label="",shape="box",style="filled",color="grey" ]; -"334" [ label="b46b0756dba915943839e90a55",color="yellow",style="filled",shape="doubleoctagon" ]; -"64E" [ label="5fdf",shape="box",style="filled",color="grey" ]; -"81E" [ label="3eca1f94dc181",shape="box",style="filled",color="grey" ]; -"82E" [ label="6b1bb9b0e",shape="box",style="filled",color="grey" ]; -"83E" [ label="a54d477232",shape="box",style="filled",color="grey" ]; -"84E" [ label="a164d9f60fbbdd",shape="box",style="filled",color="grey" ]; -"85E" [ label="78c8463ea",shape="box",style="filled",color="grey" ]; -"86E" [ label="c110ba7",shape="box",style="filled",color="grey" ]; -"87E" [ label="3b63cdc0f",shape="box",style="filled",color="grey" ]; -"88E" [ label="6f578c5128",shape="box",style="filled",color="grey" ]; -"89E" [ label="3e048573fd",shape="box",style="filled",color="grey" ]; -"336" [ URL="tes hi",area="test",label="825c7994d5da13afe519861818",color="#ff0000",style="filled",shape="tripleoctagon" ]; -"1E" [ label="f4bef37b6a94bfd00",shape="box",style="filled",color="grey" ]; -"2E" [ label="d2647f8b6d8661d08",shape="box",style="filled",color="grey" ]; -"3E" [ label="964cb56d8f69ff058",shape="box",style="filled",color="grey" ]; -"4E" [ label="4f35e206816c3bd22",shape="box",style="filled",color="grey" ]; -"5E" [ label="affb2d716803a2d3e",shape="box",style="filled",color="grey" ]; -"6E" [ label="e4ae306d9bd669c70",shape="box",style="filled",color="grey" ]; -"7E" [ label="4dbf4395236fb03ed",shape="box",style="filled",color="grey" ]; -"8E" [ label="15b3ad672cd2f713a",shape="box",style="filled",color="grey" ]; -"9E" [ label="8d6e6e0cd9b842a47",shape="box",style="filled",color="grey" ]; -"10E" [ label="00d0dd018fe879f96",shape="box",style="filled",color="grey" ]; -"11E" [ label="f28b78d4803c",shape="box",style="filled",color="grey" ]; -"12E" [ label="2d886da042b5384b4",shape="box",style="filled",color="grey" ]; -"13E" [ label="548c0081a62132b44",shape="box",style="filled",color="grey" ]; -"14E" [ label="52126553e52385d16",shape="box",style="filled",color="grey" ]; -"15E" [ label="9fe716e738eaea34e",shape="box",style="filled",color="grey" ]; -"16E" [ label="5782807b5f575e0a8",shape="box",style="filled",color="grey" ]; -"17E" [ label="792fd6f9df1fa1e33",shape="box",style="filled",color="grey" ]; -"18E" [ label="c471b6fdbfb852661",shape="box",style="filled",color="grey" ]; -"19E" [ label="a84844dfd0052b3b5",shape="box",style="filled",color="grey" ]; -"20E" [ label="724dabdce9744d061",shape="box",style="filled",color="grey" ]; -"21E" [ label="57f7fd2eecec93c8b",shape="box",style="filled",color="grey" ]; -"22E" [ label="baba65f670ee34a88",shape="box",style="filled",color="grey" ]; -"23E" [ label="ac34ec0f0488b17ec",shape="box",style="filled",color="grey" ]; -"24E" [ label="51e74bec5513083bb",shape="box",style="filled",color="grey" ]; -"25E" [ label="8e2d970b2f820ee35",shape="box",style="filled",color="grey" ]; -"26E" [ label="19398d3cd6b9c674f",shape="box",style="filled",color="grey" ]; -"27E" [ label="6505e29f4a11d9530",shape="box",style="filled",color="grey" ]; -"28E" [ label="bc4824f07a9d2bba6",shape="box",style="filled",color="grey" ]; -"29E" [ label="3acbf8a1537e4e1a1",shape="box",style="filled",color="grey" ]; -"30E" [ label="536264e787cf70469",shape="box",style="filled",color="grey" ]; -"31E" [ label="d",shape="box",style="filled",color="grey" ]; -"65E" [ label="d4b2",shape="box",style="filled",color="grey" ]; -"119E" [ label="2a9caef7",shape="box",style="filled",color="grey" ]; -"150E" [ label="73d12",shape="box",style="filled",color="grey" ]; -"176E" [ label="8896166adc0",shape="box",style="filled",color="grey" ]; -"743E" [ label="9f",shape="box",style="filled",color="grey" ]; -"744E" [ label="2e1313c",shape="box",style="filled",color="grey" ]; -"764E" [ label="cd6",shape="box",style="filled",color="grey" ]; -"337" [ label="8304a439f91fc90b3fe8dd35be8",color="yellow",style="filled",shape="doubleoctagon" ]; -"120E" [ label="345d26b3f821fe",shape="box",style="filled",color="grey" ]; -"121E" [ label="357679fea1e2f",shape="box",style="filled",color="grey" ]; -"122E" [ label="c71043819b6a79",shape="box",style="filled",color="grey" ]; -"123E" [ label="f9df653b86fb8df",shape="box",style="filled",color="grey" ]; -"124E" [ label="020df871874cd",shape="box",style="filled",color="grey" ]; -"125E" [ label="4c52fdd8e396692",shape="box",style="filled",color="grey" ]; -"126E" [ label="8b98c3ddbe0b336",shape="box",style="filled",color="grey" ]; -"127E" [ label="d9f4abac731a9e",shape="box",style="filled",color="grey" ]; -"128E" [ label="50f4d9b97aefe",shape="box",style="filled",color="grey" ]; -"129E" [ label="ea920d9f5b295119",shape="box",style="filled",color="grey" ]; -"130E" [ label="ff5c9b242337c",shape="box",style="filled",color="grey" ]; -"131E" [ label="4e12f7ff0918",shape="box",style="filled",color="grey" ]; -"132E" [ label="ee3b6be71d59b",shape="box",style="filled",color="grey" ]; -"133E" [ label="615cd6b5e3d21c",shape="box",style="filled",color="grey" ]; -"134E" [ label="6d52dd1b198bb",shape="box",style="filled",color="grey" ]; -"135E" [ label="8c932e1e502dca",shape="box",style="filled",color="grey" ]; -"136E" [ label="e84330eef281284a",shape="box",style="filled",color="grey" ]; -"137E" [ label="85fc23f1c88b4",shape="box",style="filled",color="grey" ]; -"138E" [ label="5997cb0c083422",shape="box",style="filled",color="grey" ]; -"339" [ label="b1ffbabb24d71f67d1e0ce23c51",color="yellow",style="filled",shape="doubleoctagon" ]; -"151E" [ label="",shape="box",style="filled",color="grey" ]; -"153E" [ label="41a8b095c7fd3",shape="box",style="filled",color="grey" ]; -"154E" [ label="151bcc2a8de7ea634",shape="box",style="filled",color="grey" ]; -"155E" [ label="6c541cad8de1b15",shape="box",style="filled",color="grey" ]; -"156E" [ label="c935c7f4d1090ac",shape="box",style="filled",color="grey" ]; -"157E" [ label="5ce1fcfb042b",shape="box",style="filled",color="grey" ]; -"158E" [ label="531806429433",shape="box",style="filled",color="grey" ]; -"159E" [ label="d285240b89cb",shape="box",style="filled",color="grey" ]; -"160E" [ label="f22c27c0f0a54e",shape="box",style="filled",color="grey" ]; -"161E" [ label="8d0d8314d211d80",shape="box",style="filled",color="grey" ]; -"162E" [ label="",shape="box",style="filled",color="grey" ]; -"347" [ label="9652ab8b55fdb2a36d1f3fe020",shape="hexagon" ]; -"139E" [ label="ef8b68bb5772f3",shape="box",style="filled",color="grey" ]; -"795E" [ label="16c3ae29c0bc713",shape="box",style="filled",color="grey" ]; -"348" [ label="676bbe7d1c1fb71742df534ce8",shape="hexagon" ]; -"799E" [ label="a78eb40ae56aaa9",shape="box",style="filled",color="grey" ]; -"800E" [ label="6aae8d25951",shape="box",style="filled",color="grey" ]; -"349" [ label="66c0220688a999aaf7f1702d1",shape="hexagon" ]; -"141E" [ label="67b6a4dca3a6d",shape="box",style="filled",color="grey" ]; -"350" [ label="1322fb0818783e6f9a4f173d47c52",shape="hexagon" ]; -"142E" [ label="9696c0950295d8cb5",shape="box",style="filled",color="grey" ]; -"678E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; -"351" [ label="ff07977fca5513098d220d1eb3a",shape="hexagon" ]; -"143E" [ label="89a36b13f8c344b",shape="box",style="filled",color="grey" ]; -"232E" [ label="56292d076643",shape="box",style="filled",color="grey" ]; -"680E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; -"704E" [ label="431430c49",shape="box",style="filled",color="grey" ]; -"352" [ label="a97ef281eafc34b1630d450a1df",shape="hexagon" ]; -"144E" [ label="4ff4e275c710c3b",shape="box",style="filled",color="grey" ]; -"432E" [ label="d13da6273c9b4da",shape="box",style="filled",color="grey" ]; -"353" [ label="72cbb37db85ed3c6eda5dcf8",shape="hexagon" ]; -"145E" [ label="33ff9e43d5ab",shape="box",style="filled",color="grey" ]; -"354" [ label="0f6784e49852c0be0da23b16",shape="hexagon" ]; -"146E" [ label="d4f958b03a98",shape="box",style="filled",color="grey" ]; -"396E" [ label="8e24e9b4e",shape="box",style="filled",color="grey" ]; -"355" [ label="383f5c65cc6c25aa0a0e6dbb",shape="hexagon" ]; -"147E" [ label="1ff8ff951ee9",shape="box",style="filled",color="grey" ]; -"356" [ label="f52a45620969f0df4e6ae1dcd7",shape="hexagon" ]; -"148E" [ label="5256925081c812",shape="box",style="filled",color="grey" ]; -"357" [ label="1f5df34ad75a55a76ef4afa0a47",shape="hexagon" ]; -"149E" [ label="26a185dde9a93dd",shape="box",style="filled",color="grey" ]; -"358" [ label="45ba4d4c61c9601a26d59e47e0260",shape="hexagon" ]; -"167E" [ label="99bd3e7feeb710",shape="box",style="filled",color="grey" ]; -"359" [ label="f95344b0ae31693f3a2746597d4",shape="hexagon" ]; -"169E" [ label="4e8259973f1f",shape="box",style="filled",color="grey" ]; -"360" [ label="b79798b186d6b82288e8be4017d",shape="hexagon" ]; -"171E" [ label="63b079bd5847",shape="box",style="filled",color="grey" ]; -"361" [ label="47e0067f4d853afd2012f04daa8",shape="hexagon" ]; -"172E" [ label="92fb5d4a0805",shape="box",style="filled",color="grey" ]; -"362" [ label="f2b6201774de40a29b504b1f716",shape="hexagon" ]; -"173E" [ label="d7203571944b",shape="box",style="filled",color="grey" ]; -"363" [ label="800422ab81d804eef3e7b91dfba91",shape="hexagon" ]; -"174E" [ label="952316a1a5a785",shape="box",style="filled",color="grey" ]; -"364" [ label="35b941379e1af658078cffb83a2",shape="hexagon" ]; -"101E" [ label="331675c046693f",shape="box",style="filled",color="grey" ]; -"365" [ label="d4f7b7fba7afcf7a72397353ec",shape="hexagon" ]; -"102E" [ label="32c4684b55361",shape="box",style="filled",color="grey" ]; -"367" [ label="e4b45b7a2f884d3734bfd5985656",shape="hexagon" ]; -"104E" [ label="1333074979f2d0b",shape="box",style="filled",color="grey" ]; -"368" [ label="02c2ba83680ab57f236a33d702",shape="hexagon" ]; -"105E" [ label="084d4bfa5853e",shape="box",style="filled",color="grey" ]; -"369" [ label="9ccd974150a18260b207b6584caa",shape="hexagon" ]; -"106E" [ label="28f7bfc40c88e6a",shape="box",style="filled",color="grey" ]; -"374" [ label="653ae44d45dcadeb481b53027d",shape="hexagon" ]; -"111E" [ label="8f95518f48528",shape="box",style="filled",color="grey" ]; -"375" [ label="d66f542ef1ce4d02c59bec65e",shape="hexagon" ]; -"112E" [ label="2ef209509e2a",shape="box",style="filled",color="grey" ]; -"377" [ label="a2984b7a11e49440420058c1d80",shape="hexagon" ]; -"114E" [ label="ef42184297591d",shape="box",style="filled",color="grey" ]; -"378" [ label="31055116421c96b37f72a262bb",shape="hexagon" ]; -"115E" [ label="be9c5958196ed",shape="box",style="filled",color="grey" ]; -"380" [ label="8462bb2eec1a62d19a15865e57c92",shape="hexagon" ]; -"117E" [ label="16a795a1d63f30df",shape="box",style="filled",color="grey" ]; -"392E" [ label="85a34bc9616ff",shape="box",style="filled",color="grey" ]; -"381" [ label="c21eb96fe100a1efaa128181b7",shape="hexagon" ]; -"118E" [ label="f1b0d754353a6",shape="box",style="filled",color="grey" ]; -"382" [ label="e3e284d0cc803d98d674f9c3f6d",color="yellow",style="filled",shape="doubleoctagon" ]; -"177E" [ label="30417faf916",shape="box",style="filled",color="grey" ]; -"178E" [ label="e618df70814a",shape="box",style="filled",color="grey" ]; -"179E" [ label="fa90ddf10bd574",shape="box",style="filled",color="grey" ]; -"180E" [ label="815cc0b83d733",shape="box",style="filled",color="grey" ]; -"181E" [ label="f787d827958c",shape="box",style="filled",color="grey" ]; -"182E" [ label="f20f7f513e",shape="box",style="filled",color="grey" ]; -"183E" [ label="290907417e13",shape="box",style="filled",color="grey" ]; -"184E" [ label="e8386a8e1c8a",shape="box",style="filled",color="grey" ]; -"185E" [ label="319bc900218b",shape="box",style="filled",color="grey" ]; -"186E" [ label="3ba7afb0e48ae1",shape="box",style="filled",color="grey" ]; -"187E" [ label="6ba0776fc8e",shape="box",style="filled",color="grey" ]; -"188E" [ label="09847696ae",shape="box",style="filled",color="grey" ]; -"383" [ label="908f9ad506eae9ab6ada185e3",color="yellow",style="filled",shape="doubleoctagon" ]; -"730E" [ label="65694ca6d575",shape="box",style="filled",color="grey" ]; -"732E" [ label="37f57e81ebed95",shape="box",style="filled",color="grey" ]; -"741E" [ label="9b6c",shape="box",style="filled",color="grey" ]; -"765E" [ label="88ebe2e8782c",shape="box",style="filled",color="grey" ]; -"796E" [ label="901b2105a902ee7791",shape="box",style="filled",color="grey" ]; -"384" [ label="593caebf2037317648bb451aa79",color="yellow",style="filled",shape="doubleoctagon" ]; -"726E" [ label="351dd0aefe480c",shape="box",style="filled",color="grey" ]; -"728E" [ label="56e1a896",shape="box",style="filled",color="grey" ]; -"742E" [ label="5ba4693031",shape="box",style="filled",color="grey" ]; -"385" [ label="717c254aeffbb527dabfc",shape="hexagon" ]; -"328E" [ label="123cc6d1ac",shape="box",style="filled",color="grey" ]; -"496E" [ label="",shape="box",style="filled",color="grey" ]; -"594E" [ label="7f8c557bcf3889",shape="box",style="filled",color="grey" ]; -"622E" [ label="da3d5",shape="box",style="filled",color="grey" ]; -"754E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; -"755E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; -"756E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"757E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; -"758E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; -"759E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"760E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; -"761E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; -"762E" [ label="1e2298c4bb",shape="box",style="filled",color="grey" ]; -"1" -> "189E" [ label=" ",color="blue",arrowhead="dot" ]; -"1" -> "790E" [ label=" ",color="blue",arrowhead="dot" ]; -"2" -> "191E" [ label=" ",color="blue",arrowhead="dot" ]; -"3" -> "193E" [ label=" ",color="blue",arrowhead="dot" ]; -"4" -> "195E" [ label=" ",color="blue",arrowhead="dot" ]; -"5" -> "197E" [ label=" ",color="blue",arrowhead="dot" ]; -"6" -> "199E" [ label=" ",color="blue",arrowhead="dot" ]; -"7" -> "201E" [ label=" ",color="blue",arrowhead="dot" ]; -"8" -> "203E" [ label=" ",color="blue",arrowhead="dot" ]; -"9" -> "725E" [ label=" ",color="blue",arrowhead="dot" ]; -"9" -> "785E" [ label=" ",color="blue",arrowhead="dot" ]; -"10" -> "205E" [ label=" ",color="blue",arrowhead="dot" ]; -"11" -> "207E" [ label=" ",color="blue",arrowhead="dot" ]; -"12" -> "209E" [ label=" ",color="blue",arrowhead="dot" ]; -"13" -> "211E" [ label=" ",color="blue",arrowhead="dot" ]; -"14" -> "213E" [ label=" ",color="blue",arrowhead="dot" ]; -"15" -> "215E" [ label=" ",color="blue",arrowhead="dot" ]; -"16" -> "727E" [ label=" ",color="blue",arrowhead="dot" ]; -"16" -> "784E" [ label=" ",color="blue",arrowhead="dot" ]; -"17" -> "217E" [ label=" ",color="blue",arrowhead="dot" ]; -"17" -> "787E" [ label=" ",color="blue",arrowhead="dot" ]; -"18" -> "219E" [ label=" ",color="blue",arrowhead="dot" ]; -"19" -> "221E" [ label=" ",color="blue",arrowhead="dot" ]; -"20" -> "223E" [ label=" ",color="blue",arrowhead="dot" ]; -"21" -> "225E" [ label=" ",color="blue",arrowhead="dot" ]; -"22" -> "227E" [ label=" ",color="blue",arrowhead="dot" ]; -"22" -> "792E" [ label=" ",color="blue",arrowhead="dot" ]; -"23" -> "231E" [ label=" ",color="blue",arrowhead="dot" ]; -"24" -> "233E" [ label=" ",color="blue",arrowhead="dot" ]; -"25" -> "235E" [ label=" ",color="blue",arrowhead="dot" ]; -"26" -> "237E" [ label=" ",color="blue",arrowhead="dot" ]; -"27" -> "239E" [ label=" ",color="blue",arrowhead="dot" ]; -"27" -> "783E" [ label=" ",color="blue",arrowhead="dot" ]; -"28" -> "241E" [ label=" ",color="blue",arrowhead="dot" ]; -"28" -> "791E" [ label=" ",color="blue",arrowhead="dot" ]; -"29" -> "243E" [ label=" ",color="blue",arrowhead="dot" ]; -"30" -> "245E" [ label=" ",color="blue",arrowhead="dot" ]; -"31" -> "247E" [ label=" ",color="blue",arrowhead="dot" ]; -"32" -> "249E" [ label=" ",color="blue",arrowhead="dot" ]; -"33" -> "251E" [ label=" ",color="blue",arrowhead="dot" ]; -"34" -> "253E" [ label=" ",color="blue",arrowhead="dot" ]; -"35" -> "255E" [ label=" ",color="blue",arrowhead="dot" ]; -"36" -> "257E" [ label=" ",color="blue",arrowhead="dot" ]; -"37" -> "259E" [ label=" ",color="blue",arrowhead="dot" ]; -"38" -> "261E" [ label=" ",color="blue",arrowhead="dot" ]; -"39" -> "263E" [ label=" ",color="blue",arrowhead="dot" ]; -"40" -> "265E" [ label=" ",color="blue",arrowhead="dot" ]; -"41" -> "267E" [ label=" ",color="blue",arrowhead="dot" ]; -"42" -> "269E" [ label=" ",color="blue",arrowhead="dot" ]; -"43" -> "271E" [ label=" ",color="blue",arrowhead="dot" ]; -"44" -> "273E" [ label=" ",color="blue",arrowhead="dot" ]; -"45" -> "275E" [ label=" ",color="blue",arrowhead="dot" ]; -"46" -> "277E" [ label=" ",color="blue",arrowhead="dot" ]; -"47" -> "279E" [ label=" ",color="blue",arrowhead="dot" ]; -"48" -> "281E" [ label=" ",color="blue",arrowhead="dot" ]; -"49" -> "283E" [ label=" ",color="blue",arrowhead="dot" ]; -"50" -> "285E" [ label=" ",color="blue",arrowhead="dot" ]; -"51" -> "287E" [ label=" ",color="blue",arrowhead="dot" ]; -"52" -> "289E" [ label=" ",color="blue",arrowhead="dot" ]; -"53" -> "291E" [ label=" ",color="blue",arrowhead="dot" ]; -"54" -> "293E" [ label=" ",color="blue",arrowhead="dot" ]; -"55" -> "745E" [ label=" ",color="blue",arrowhead="dot" ]; -"56" -> "295E" [ label=" ",color="blue",arrowhead="dot" ]; -"57" -> "297E" [ label=" ",color="blue",arrowhead="dot" ]; -"58" -> "299E" [ label=" ",color="blue",arrowhead="dot" ]; -"59" -> "301E" [ label=" ",color="blue",arrowhead="dot" ]; -"59" -> "789E" [ label=" ",color="blue",arrowhead="dot" ]; -"60" -> "303E" [ label=" ",color="blue",arrowhead="dot" ]; -"61" -> "305E" [ label=" ",color="blue",arrowhead="dot" ]; -"62" -> "307E" [ label=" ",color="blue",arrowhead="dot" ]; -"63" -> "309E" [ label=" ",color="blue",arrowhead="dot" ]; -"64" -> "311E" [ label=" ",color="blue",arrowhead="dot" ]; -"65" -> "313E" [ label=" ",color="blue",arrowhead="dot" ]; -"66" -> "315E" [ label=" ",color="blue",arrowhead="dot" ]; -"67" -> "317E" [ label=" ",color="blue",arrowhead="dot" ]; -"68" -> "319E" [ label=" ",color="blue",arrowhead="dot" ]; -"69" -> "746E" [ label=" ",color="blue",arrowhead="dot" ]; -"70" -> "321E" [ label=" ",color="blue",arrowhead="dot" ]; -"71" -> "327E" [ label=" ",color="blue",arrowhead="dot" ]; -"72" -> "329E" [ label=" ",color="blue",arrowhead="dot" ]; -"73" -> "331E" [ label=" ",color="blue",arrowhead="dot" ]; -"74" -> "333E" [ label=" ",color="blue",arrowhead="dot" ]; -"75" -> "335E" [ label=" ",color="blue",arrowhead="dot" ]; -"76" -> "337E" [ label=" ",color="blue",arrowhead="dot" ]; -"77" -> "339E" [ label=" ",color="blue",arrowhead="dot" ]; -"78" -> "341E" [ label=" ",color="blue",arrowhead="dot" ]; -"79" -> "343E" [ label=" ",color="blue",arrowhead="dot" ]; -"80" -> "345E" [ label=" ",color="blue",arrowhead="dot" ]; -"81" -> "347E" [ label=" ",color="blue",arrowhead="dot" ]; -"82" -> "349E" [ label=" ",color="blue",arrowhead="dot" ]; -"83" -> "351E" [ label=" ",color="blue",arrowhead="dot" ]; -"84" -> "353E" [ label=" ",color="blue",arrowhead="dot" ]; -"85" -> "355E" [ label=" ",color="blue",arrowhead="dot" ]; -"85" -> "788E" [ label=" ",color="blue",arrowhead="dot" ]; -"86" -> "357E" [ label=" ",color="blue",arrowhead="dot" ]; -"87" -> "359E" [ label=" ",color="blue",arrowhead="dot" ]; -"88" -> "361E" [ label=" ",color="blue",arrowhead="dot" ]; -"89" -> "363E" [ label=" ",color="blue",arrowhead="dot" ]; -"90" -> "365E" [ label=" ",color="blue",arrowhead="dot" ]; -"91" -> "367E" [ label=" ",color="blue",arrowhead="dot" ]; -"92" -> "369E" [ label=" ",color="blue",arrowhead="dot" ]; -"93" -> "729E" [ label=" ",color="blue",arrowhead="dot" ]; -"94" -> "371E" [ label=" ",color="blue",arrowhead="dot" ]; -"95" -> "373E" [ label=" ",color="blue",arrowhead="dot" ]; -"96" -> "375E" [ label=" ",color="blue",arrowhead="dot" ]; -"97" -> "747E" [ label=" ",color="blue",arrowhead="dot" ]; -"98" -> "377E" [ label=" ",color="blue",arrowhead="dot" ]; -"99" -> "379E" [ label=" ",color="blue",arrowhead="dot" ]; -"100" -> "381E" [ label=" ",color="blue",arrowhead="dot" ]; -"101" -> "383E" [ label=" ",color="blue",arrowhead="dot" ]; -"102" -> "385E" [ label=" ",color="blue",arrowhead="dot" ]; -"103" -> "387E" [ label=" ",color="blue",arrowhead="dot" ]; -"104" -> "389E" [ label=" ",color="blue",arrowhead="dot" ]; -"105" -> "391E" [ label=" ",color="blue",arrowhead="dot" ]; -"106" -> "393E" [ label=" ",color="blue",arrowhead="dot" ]; -"107" -> "395E" [ label=" ",color="blue",arrowhead="dot" ]; -"108" -> "397E" [ label=" ",color="blue",arrowhead="dot" ]; -"109" -> "399E" [ label=" ",color="blue",arrowhead="dot" ]; -"110" -> "401E" [ label=" ",color="blue",arrowhead="dot" ]; -"111" -> "403E" [ label=" ",color="blue",arrowhead="dot" ]; -"112" -> "405E" [ label=" ",color="blue",arrowhead="dot" ]; -"113" -> "407E" [ label=" ",color="blue",arrowhead="dot" ]; -"114" -> "409E" [ label=" ",color="blue",arrowhead="dot" ]; -"115" -> "411E" [ label=" ",color="blue",arrowhead="dot" ]; -"116" -> "413E" [ label=" ",color="blue",arrowhead="dot" ]; -"117" -> "415E" [ label=" ",color="blue",arrowhead="dot" ]; -"118" -> "417E" [ label=" ",color="blue",arrowhead="dot" ]; -"119" -> "419E" [ label=" ",color="blue",arrowhead="dot" ]; -"120" -> "421E" [ label=" ",color="blue",arrowhead="dot" ]; -"121" -> "423E" [ label=" ",color="blue",arrowhead="dot" ]; -"122" -> "748E" [ label=" ",color="blue",arrowhead="dot" ]; -"123" -> "425E" [ label=" ",color="blue",arrowhead="dot" ]; -"124" -> "427E" [ label=" ",color="blue",arrowhead="dot" ]; -"124" -> "786E" [ label=" ",color="blue",arrowhead="dot" ]; -"125" -> "431E" [ label=" ",color="blue",arrowhead="dot" ]; -"126" -> "433E" [ label=" ",color="blue",arrowhead="dot" ]; -"127" -> "435E" [ label=" ",color="blue",arrowhead="dot" ]; -"128" -> "437E" [ label=" ",color="blue",arrowhead="dot" ]; -"129" -> "439E" [ label=" ",color="blue",arrowhead="dot" ]; -"130" -> "441E" [ label=" ",color="blue",arrowhead="dot" ]; -"131" -> "443E" [ label=" ",color="blue",arrowhead="dot" ]; -"132" -> "445E" [ label=" ",color="blue",arrowhead="dot" ]; -"133" -> "749E" [ label=" ",color="blue",arrowhead="dot" ]; -"134" -> "447E" [ label=" ",color="blue",arrowhead="dot" ]; -"135" -> "449E" [ label=" ",color="blue",arrowhead="dot" ]; -"135" -> "769E" [ label=" ",color="blue",arrowhead="dot" ]; -"135" -> "770E" [ label=" ",color="blue",arrowhead="dot" ]; -"136" -> "451E" [ label=" ",color="blue",arrowhead="dot" ]; -"137" -> "453E" [ label=" ",color="blue",arrowhead="dot" ]; -"138" -> "455E" [ label=" ",color="blue",arrowhead="dot" ]; -"139" -> "457E" [ label=" ",color="blue",arrowhead="dot" ]; -"140" -> "459E" [ label=" ",color="blue",arrowhead="dot" ]; -"141" -> "461E" [ label=" ",color="blue",arrowhead="dot" ]; -"142" -> "463E" [ label=" ",color="blue",arrowhead="dot" ]; -"143" -> "465E" [ label=" ",color="blue",arrowhead="dot" ]; -"144" -> "467E" [ label=" ",color="blue",arrowhead="dot" ]; -"145" -> "469E" [ label=" ",color="blue",arrowhead="dot" ]; -"146" -> "471E" [ label=" ",color="blue",arrowhead="dot" ]; -"147" -> "473E" [ label=" ",color="blue",arrowhead="dot" ]; -"148" -> "475E" [ label=" ",color="blue",arrowhead="dot" ]; -"149" -> "477E" [ label=" ",color="blue",arrowhead="dot" ]; -"150" -> "479E" [ label=" ",color="blue",arrowhead="dot" ]; -"151" -> "481E" [ label=" ",color="blue",arrowhead="dot" ]; -"152" -> "483E" [ label=" ",color="blue",arrowhead="dot" ]; -"153" -> "731E" [ label=" ",color="blue",arrowhead="dot" ]; -"154" -> "750E" [ label=" ",color="blue",arrowhead="dot" ]; -"155" -> "485E" [ label=" ",color="blue",arrowhead="dot" ]; -"156" -> "487E" [ label=" ",color="blue",arrowhead="dot" ]; -"157" -> "489E" [ label=" ",color="blue",arrowhead="dot" ]; -"158" -> "491E" [ label=" ",color="blue",arrowhead="dot" ]; -"159" -> "495E" [ label=" ",color="blue",arrowhead="dot" ]; -"160" -> "499E" [ label=" ",color="blue",arrowhead="dot" ]; -"161" -> "501E" [ label=" ",color="blue",arrowhead="dot" ]; -"162" -> "503E" [ label=" ",color="blue",arrowhead="dot" ]; -"163" -> "505E" [ label=" ",color="blue",arrowhead="dot" ]; -"164" -> "507E" [ label=" ",color="blue",arrowhead="dot" ]; -"165" -> "509E" [ label=" ",color="blue",arrowhead="dot" ]; -"166" -> "511E" [ label=" ",color="blue",arrowhead="dot" ]; -"167" -> "513E" [ label=" ",color="blue",arrowhead="dot" ]; -"168" -> "515E" [ label=" ",color="blue",arrowhead="dot" ]; -"169" -> "517E" [ label=" ",color="blue",arrowhead="dot" ]; -"170" -> "519E" [ label=" ",color="blue",arrowhead="dot" ]; -"171" -> "521E" [ label=" ",color="blue",arrowhead="dot" ]; -"172" -> "523E" [ label=" ",color="blue",arrowhead="dot" ]; -"173" -> "525E" [ label=" ",color="blue",arrowhead="dot" ]; -"174" -> "527E" [ label=" ",color="blue",arrowhead="dot" ]; -"175" -> "529E" [ label=" ",color="blue",arrowhead="dot" ]; -"176" -> "531E" [ label=" ",color="blue",arrowhead="dot" ]; -"177" -> "533E" [ label=" ",color="blue",arrowhead="dot" ]; -"178" -> "535E" [ label=" ",color="blue",arrowhead="dot" ]; -"179" -> "537E" [ label=" ",color="blue",arrowhead="dot" ]; -"180" -> "539E" [ label=" ",color="blue",arrowhead="dot" ]; -"181" -> "541E" [ label=" ",color="blue",arrowhead="dot" ]; -"182" -> "543E" [ label=" ",color="blue",arrowhead="dot" ]; -"183" -> "545E" [ label=" ",color="blue",arrowhead="dot" ]; -"184" -> "547E" [ label=" ",color="blue",arrowhead="dot" ]; -"185" -> "549E" [ label=" ",color="blue",arrowhead="dot" ]; -"186" -> "551E" [ label=" ",color="blue",arrowhead="dot" ]; -"187" -> "553E" [ label=" ",color="blue",arrowhead="dot" ]; -"188" -> "555E" [ label=" ",color="blue",arrowhead="dot" ]; -"189" -> "557E" [ label=" ",color="blue",arrowhead="dot" ]; -"190" -> "559E" [ label=" ",color="blue",arrowhead="dot" ]; -"191" -> "561E" [ label=" ",color="blue",arrowhead="dot" ]; -"192" -> "563E" [ label=" ",color="blue",arrowhead="dot" ]; -"193" -> "565E" [ label=" ",color="blue",arrowhead="dot" ]; -"194" -> "567E" [ label=" ",color="blue",arrowhead="dot" ]; -"195" -> "569E" [ label=" ",color="blue",arrowhead="dot" ]; -"196" -> "571E" [ label=" ",color="blue",arrowhead="dot" ]; -"197" -> "573E" [ label=" ",color="blue",arrowhead="dot" ]; -"198" -> "575E" [ label=" ",color="blue",arrowhead="dot" ]; -"199" -> "577E" [ label=" ",color="blue",arrowhead="dot" ]; -"200" -> "579E" [ label=" ",color="blue",arrowhead="dot" ]; -"201" -> "581E" [ label=" ",color="blue",arrowhead="dot" ]; -"202" -> "583E" [ label=" ",color="blue",arrowhead="dot" ]; -"203" -> "585E" [ label=" ",color="blue",arrowhead="dot" ]; -"204" -> "587E" [ label=" ",color="blue",arrowhead="dot" ]; -"205" -> "751E" [ label=" ",color="blue",arrowhead="dot" ]; -"206" -> "589E" [ label=" ",color="blue",arrowhead="dot" ]; -"207" -> "593E" [ label=" ",color="blue",arrowhead="dot" ]; -"208" -> "597E" [ label=" ",color="blue",arrowhead="dot" ]; -"209" -> "599E" [ label=" ",color="blue",arrowhead="dot" ]; -"210" -> "601E" [ label=" ",color="blue",arrowhead="dot" ]; -"211" -> "603E" [ label=" ",color="blue",arrowhead="dot" ]; -"212" -> "605E" [ label=" ",color="blue",arrowhead="dot" ]; -"213" -> "607E" [ label=" ",color="blue",arrowhead="dot" ]; -"214" -> "609E" [ label=" ",color="blue",arrowhead="dot" ]; -"215" -> "611E" [ label=" ",color="blue",arrowhead="dot" ]; -"216" -> "613E" [ label=" ",color="blue",arrowhead="dot" ]; -"217" -> "615E" [ label=" ",color="blue",arrowhead="dot" ]; -"218" -> "617E" [ label=" ",color="blue",arrowhead="dot" ]; -"219" -> "619E" [ label=" ",color="blue",arrowhead="dot" ]; -"220" -> "621E" [ label=" ",color="blue",arrowhead="dot" ]; -"221" -> "623E" [ label=" ",color="blue",arrowhead="dot" ]; -"222" -> "752E" [ label=" ",color="blue",arrowhead="dot" ]; -"223" -> "625E" [ label=" ",color="blue",arrowhead="dot" ]; -"224" -> "627E" [ label=" ",color="blue",arrowhead="dot" ]; -"225" -> "629E" [ label=" ",color="blue",arrowhead="dot" ]; -"226" -> "631E" [ label=" ",color="blue",arrowhead="dot" ]; -"227" -> "633E" [ label=" ",color="blue",arrowhead="dot" ]; -"228" -> "635E" [ label=" ",color="blue",arrowhead="dot" ]; -"229" -> "637E" [ label=" ",color="blue",arrowhead="dot" ]; -"230" -> "639E" [ label=" ",color="blue",arrowhead="dot" ]; -"231" -> "641E" [ label=" ",color="blue",arrowhead="dot" ]; -"232" -> "643E" [ label=" ",color="blue",arrowhead="dot" ]; -"233" -> "645E" [ label=" ",color="blue",arrowhead="dot" ]; -"234" -> "647E" [ label=" ",color="blue",arrowhead="dot" ]; -"235" -> "649E" [ label=" ",color="blue",arrowhead="dot" ]; -"236" -> "651E" [ label=" ",color="blue",arrowhead="dot" ]; -"237" -> "653E" [ label=" ",color="blue",arrowhead="dot" ]; -"238" -> "655E" [ label=" ",color="blue",arrowhead="dot" ]; -"239" -> "657E" [ label=" ",color="blue",arrowhead="dot" ]; -"240" -> "659E" [ label=" ",color="blue",arrowhead="dot" ]; -"241" -> "661E" [ label=" ",color="blue",arrowhead="dot" ]; -"242" -> "663E" [ label=" ",color="blue",arrowhead="dot" ]; -"243" -> "665E" [ label=" ",color="blue",arrowhead="dot" ]; -"244" -> "667E" [ label=" ",color="blue",arrowhead="dot" ]; -"245" -> "669E" [ label=" ",color="blue",arrowhead="dot" ]; -"246" -> "671E" [ label=" ",color="blue",arrowhead="dot" ]; -"247" -> "673E" [ label=" ",color="blue",arrowhead="dot" ]; -"248" -> "675E" [ label=" ",color="blue",arrowhead="dot" ]; -"249" -> "679E" [ label=" ",color="blue",arrowhead="dot" ]; -"250" -> "753E" [ label=" ",color="blue",arrowhead="dot" ]; -"251" -> "681E" [ label=" ",color="blue",arrowhead="dot" ]; -"252" -> "683E" [ label=" ",color="blue",arrowhead="dot" ]; -"253" -> "685E" [ label=" ",color="blue",arrowhead="dot" ]; -"254" -> "687E" [ label=" ",color="blue",arrowhead="dot" ]; -"255" -> "689E" [ label=" ",color="blue",arrowhead="dot" ]; -"256" -> "691E" [ label=" ",color="blue",arrowhead="dot" ]; -"257" -> "693E" [ label=" ",color="blue",arrowhead="dot" ]; -"258" -> "695E" [ label=" ",color="blue",arrowhead="dot" ]; -"259" -> "697E" [ label=" ",color="blue",arrowhead="dot" ]; -"260" -> "699E" [ label=" ",color="blue",arrowhead="dot" ]; -"261" -> "703E" [ label=" ",color="blue",arrowhead="dot" ]; -"262" -> "705E" [ label=" ",color="blue",arrowhead="dot" ]; -"264" -> "709E" [ label=" ",color="blue",arrowhead="dot" ]; -"265" -> "711E" [ label=" ",color="blue",arrowhead="dot" ]; -"266" -> "713E" [ label=" ",color="blue",arrowhead="dot" ]; -"267" -> "715E" [ label=" ",color="blue",arrowhead="dot" ]; -"268" -> "717E" [ label=" ",color="blue",arrowhead="dot" ]; -"269" -> "719E" [ label=" ",color="blue",arrowhead="dot" ]; -"270" -> "721E" [ label=" ",color="blue",arrowhead="dot" ]; -"272" -> "34E" [ label=" ",color="blue",arrowhead="dot" ]; -"272" -> "252E" [ label=" ",color="blue",arrowhead="dot" ]; -"272" -> "436E" [ label=" ",color="blue",arrowhead="dot" ]; -"274" -> "59E" [ label=" ",color="blue",arrowhead="dot" ]; -"274" -> "500E" [ label=" ",color="blue",arrowhead="dot" ]; -"274" -> "720E" [ label=" ",color="blue",arrowhead="dot" ]; -"275" -> "98E" [ label=" ",color="blue",arrowhead="dot" ]; -"278" -> "35E" [ label=" ",color="blue",arrowhead="dot" ]; -"278" -> "488E" [ label=" ",color="blue",arrowhead="dot" ]; -"278" -> "598E" [ label=" ",color="blue",arrowhead="dot" ]; -"278" -> "604E" [ label=" ",color="blue",arrowhead="dot" ]; -"278" -> "628E" [ label=" ",color="blue",arrowhead="dot" ]; -"279" -> "99E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "242E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "270E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "272E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "284E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "286E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "288E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "586E" [ label=" ",color="blue",arrowhead="dot" ]; -"280" -> "763E" [ label=" ",color="blue",arrowhead="dot" ]; -"281" -> "45E" [ label=" ",color="blue",arrowhead="dot" ]; -"281" -> "470E" [ label=" ",color="blue",arrowhead="dot" ]; -"281" -> "670E" [ label=" ",color="blue",arrowhead="dot" ]; -"281" -> "722E" [ label=" ",color="blue",arrowhead="dot" ]; -"282" -> "103E" [ label=" ",color="blue",arrowhead="dot" ]; -"283" -> "165E" [ label=" ",color="blue",arrowhead="dot" ]; -"284" -> "39E" [ label=" ",color="blue",arrowhead="dot" ]; -"284" -> "224E" [ label=" ",color="blue",arrowhead="dot" ]; -"284" -> "268E" [ label=" ",color="blue",arrowhead="dot" ]; -"284" -> "632E" [ label=" ",color="blue",arrowhead="dot" ]; -"284" -> "710E" [ label=" ",color="blue",arrowhead="dot" ]; -"285" -> "53E" [ label=" ",color="blue",arrowhead="dot" ]; -"286" -> "38E" [ label=" ",color="blue",arrowhead="dot" ]; -"286" -> "166E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "40E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "218E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "244E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "246E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "258E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "290E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "292E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "308E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "318E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "388E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "472E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "478E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "566E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "570E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "574E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "608E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "614E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "658E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "664E" [ label=" ",color="blue",arrowhead="dot" ]; -"288" -> "682E" [ label=" ",color="blue",arrowhead="dot" ]; -"289" -> "41E" [ label=" ",color="blue",arrowhead="dot" ]; -"289" -> "636E" [ label=" ",color="blue",arrowhead="dot" ]; -"289" -> "642E" [ label=" ",color="blue",arrowhead="dot" ]; -"289" -> "690E" [ label=" ",color="blue",arrowhead="dot" ]; -"289" -> "700E" [ label=" ",color="blue",arrowhead="dot" ]; -"290" -> "56E" [ label=" ",color="blue",arrowhead="dot" ]; -"290" -> "264E" [ label=" ",color="blue",arrowhead="dot" ]; -"290" -> "510E" [ label=" ",color="blue",arrowhead="dot" ]; -"290" -> "718E" [ label=" ",color="blue",arrowhead="dot" ]; -"291" -> "66E" [ label=" ",color="blue",arrowhead="dot" ]; -"291" -> "76E" [ label=" ",color="blue",arrowhead="dot" ]; -"291" -> "610E" [ label=" ",color="blue",arrowhead="dot" ]; -"292" -> "73E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "49E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "214E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "216E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "236E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "278E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "358E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "398E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "400E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "402E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "404E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "406E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "408E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "412E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "438E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "448E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "476E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "504E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "552E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "634E" [ label=" ",color="blue",arrowhead="dot" ]; -"293" -> "768E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "44E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "92E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "250E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "316E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "380E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "424E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "442E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "446E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "454E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "460E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "462E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "648E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "656E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "666E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "692E" [ label=" ",color="blue",arrowhead="dot" ]; -"295" -> "712E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "47E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "330E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "514E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "516E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "518E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "520E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "522E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "526E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "528E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "530E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "532E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "534E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "536E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "538E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "540E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "542E" [ label=" ",color="blue",arrowhead="dot" ]; -"296" -> "544E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "46E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "93E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "206E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "426E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "550E" [ label=" ",color="blue",arrowhead="dot" ]; -"297" -> "706E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "36E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "95E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "364E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "394E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "420E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "456E" [ label=" ",color="blue",arrowhead="dot" ]; -"298" -> "624E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "48E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "168E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "260E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "282E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "554E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "590E" [ label=" ",color="blue",arrowhead="dot" ]; -"299" -> "767E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "62E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "190E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "226E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "238E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "254E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "256E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "262E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "266E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "274E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "276E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "294E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "296E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "310E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "320E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "322E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "332E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "340E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "344E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "346E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "348E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "374E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "378E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "452E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "508E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "524E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "612E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "626E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "638E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "644E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "654E" [ label=" ",color="blue",arrowhead="dot" ]; -"300" -> "672E" [ label=" ",color="blue",arrowhead="dot" ]; -"302" -> "797E" [ label=" ",color="blue",arrowhead="dot" ]; -"302" -> "798E" [ label=" ",color="blue",arrowhead="dot" ]; -"303" -> "52E" [ label=" ",color="blue",arrowhead="dot" ]; -"303" -> "650E" [ label=" ",color="blue",arrowhead="dot" ]; -"304" -> "50E" [ label=" ",color="blue",arrowhead="dot" ]; -"304" -> "640E" [ label=" ",color="blue",arrowhead="dot" ]; -"304" -> "646E" [ label=" ",color="blue",arrowhead="dot" ]; -"304" -> "652E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "55E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "220E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "338E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "368E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "486E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "490E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "562E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "564E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "600E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "668E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "674E" [ label=" ",color="blue",arrowhead="dot" ]; -"306" -> "698E" [ label=" ",color="blue",arrowhead="dot" ]; -"307" -> "107E" [ label=" ",color="blue",arrowhead="dot" ]; -"308" -> "108E" [ label=" ",color="blue",arrowhead="dot" ]; -"309" -> "109E" [ label=" ",color="blue",arrowhead="dot" ]; -"310" -> "110E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "58E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "234E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "300E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "306E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "314E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "342E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "354E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "370E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "382E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "422E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "444E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "582E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "620E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "630E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "684E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "696E" [ label=" ",color="blue",arrowhead="dot" ]; -"311" -> "801E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "42E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "192E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "194E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "196E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "198E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "200E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "202E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "204E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "312E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "336E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "376E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "384E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "386E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "428E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "474E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "484E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "546E" [ label=" ",color="blue",arrowhead="dot" ]; -"312" -> "548E" [ label=" ",color="blue",arrowhead="dot" ]; -"314" -> "113E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "43E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "240E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "298E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "334E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "360E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "390E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "418E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "492E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "502E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "584E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "588E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "602E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "606E" [ label=" ",color="blue",arrowhead="dot" ]; -"315" -> "662E" [ label=" ",color="blue",arrowhead="dot" ]; -"316" -> "51E" [ label=" ",color="blue",arrowhead="dot" ]; -"317" -> "116E" [ label=" ",color="blue",arrowhead="dot" ]; -"318" -> "74E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "57E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "94E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "350E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "440E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "466E" [ label=" ",color="blue",arrowhead="dot" ]; -"319" -> "676E" [ label=" ",color="blue",arrowhead="dot" ]; -"320" -> "60E" [ label=" ",color="blue",arrowhead="dot" ]; -"320" -> "366E" [ label=" ",color="blue",arrowhead="dot" ]; -"320" -> "434E" [ label=" ",color="blue",arrowhead="dot" ]; -"320" -> "458E" [ label=" ",color="blue",arrowhead="dot" ]; -"320" -> "618E" [ label=" ",color="blue",arrowhead="dot" ]; -"321" -> "72E" [ label=" ",color="blue",arrowhead="dot" ]; -"321" -> "362E" [ label=" ",color="blue",arrowhead="dot" ]; -"321" -> "372E" [ label=" ",color="blue",arrowhead="dot" ]; -"321" -> "572E" [ label=" ",color="blue",arrowhead="dot" ]; -"322" -> "54E" [ label=" ",color="blue",arrowhead="dot" ]; -"322" -> "222E" [ label=" ",color="blue",arrowhead="dot" ]; -"322" -> "302E" [ label=" ",color="blue",arrowhead="dot" ]; -"322" -> "556E" [ label=" ",color="blue",arrowhead="dot" ]; -"322" -> "558E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "37E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "208E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "210E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "352E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "450E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "568E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "576E" [ label=" ",color="blue",arrowhead="dot" ]; -"323" -> "686E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "228E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "248E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "304E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "468E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "578E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "660E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "688E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "694E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "714E" [ label=" ",color="blue",arrowhead="dot" ]; -"324" -> "766E" [ label=" ",color="blue",arrowhead="dot" ]; -"325" -> "97E" [ label=" ",color="blue",arrowhead="dot" ]; -"325" -> "506E" [ label=" ",color="blue",arrowhead="dot" ]; -"326" -> "61E" [ label=" ",color="blue",arrowhead="dot" ]; -"326" -> "175E" [ label=" ",color="blue",arrowhead="dot" ]; -"326" -> "482E" [ label=" ",color="blue",arrowhead="dot" ]; -"328" -> "75E" [ label=" ",color="blue",arrowhead="dot" ]; -"328" -> "580E" [ label=" ",color="blue",arrowhead="dot" ]; -"329" -> "96E" [ label=" ",color="blue",arrowhead="dot" ]; -"330" -> "100E" [ label=" ",color="blue",arrowhead="dot" ]; -"330" -> "170E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "63E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "67E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "68E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "69E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "70E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "71E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "802E" [ label=" ",color="blue",arrowhead="dot" ]; -"333" -> "793E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "64E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "81E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "82E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "83E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "84E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "85E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "86E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "87E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "88E" [ label=" ",color="blue",arrowhead="dot" ]; -"334" -> "89E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "1E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "2E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "3E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "4E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "5E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "6E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "7E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "8E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "9E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "10E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "11E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "12E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "13E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "14E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "15E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "16E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "17E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "18E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "19E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "20E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "21E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "22E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "23E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "24E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "25E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "26E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "27E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "28E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "29E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "30E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "31E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "65E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "119E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "150E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "176E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "743E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "744E" [ label=" ",color="blue",arrowhead="dot" ]; -"336" -> "764E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "120E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "121E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "122E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "123E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "124E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "125E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "126E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "127E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "128E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "129E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "130E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "131E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "132E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "133E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "134E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "135E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "136E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "137E" [ label=" ",color="blue",arrowhead="dot" ]; -"337" -> "138E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "151E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "153E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "154E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "155E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "156E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "157E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "158E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "159E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "160E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "161E" [ label=" ",color="blue",arrowhead="dot" ]; -"339" -> "162E" [ label=" ",color="blue",arrowhead="dot" ]; -"347" -> "139E" [ label=" ",color="blue",arrowhead="dot" ]; -"347" -> "795E" [ label=" ",color="blue",arrowhead="dot" ]; -"348" -> "799E" [ label=" ",color="blue",arrowhead="dot" ]; -"348" -> "800E" [ label=" ",color="blue",arrowhead="dot" ]; -"349" -> "141E" [ label=" ",color="blue",arrowhead="dot" ]; -"350" -> "142E" [ label=" ",color="blue",arrowhead="dot" ]; -"350" -> "678E" [ label=" ",color="blue",arrowhead="dot" ]; -"351" -> "143E" [ label=" ",color="blue",arrowhead="dot" ]; -"351" -> "232E" [ label=" ",color="blue",arrowhead="dot" ]; -"351" -> "680E" [ label=" ",color="blue",arrowhead="dot" ]; -"351" -> "704E" [ label=" ",color="blue",arrowhead="dot" ]; -"352" -> "144E" [ label=" ",color="blue",arrowhead="dot" ]; -"352" -> "432E" [ label=" ",color="blue",arrowhead="dot" ]; -"353" -> "145E" [ label=" ",color="blue",arrowhead="dot" ]; -"354" -> "146E" [ label=" ",color="blue",arrowhead="dot" ]; -"354" -> "396E" [ label=" ",color="blue",arrowhead="dot" ]; -"355" -> "147E" [ label=" ",color="blue",arrowhead="dot" ]; -"356" -> "148E" [ label=" ",color="blue",arrowhead="dot" ]; -"357" -> "149E" [ label=" ",color="blue",arrowhead="dot" ]; -"358" -> "167E" [ label=" ",color="blue",arrowhead="dot" ]; -"359" -> "169E" [ label=" ",color="blue",arrowhead="dot" ]; -"360" -> "171E" [ label=" ",color="blue",arrowhead="dot" ]; -"361" -> "172E" [ label=" ",color="blue",arrowhead="dot" ]; -"362" -> "173E" [ label=" ",color="blue",arrowhead="dot" ]; -"363" -> "174E" [ label=" ",color="blue",arrowhead="dot" ]; -"364" -> "101E" [ label=" ",color="blue",arrowhead="dot" ]; -"365" -> "102E" [ label=" ",color="blue",arrowhead="dot" ]; -"367" -> "104E" [ label=" ",color="blue",arrowhead="dot" ]; -"368" -> "105E" [ label=" ",color="blue",arrowhead="dot" ]; -"369" -> "106E" [ label=" ",color="blue",arrowhead="dot" ]; -"374" -> "111E" [ label=" ",color="blue",arrowhead="dot" ]; -"375" -> "112E" [ label=" ",color="blue",arrowhead="dot" ]; -"377" -> "114E" [ label=" ",color="blue",arrowhead="dot" ]; -"378" -> "115E" [ label=" ",color="blue",arrowhead="dot" ]; -"380" -> "117E" [ label=" ",color="blue",arrowhead="dot" ]; -"380" -> "392E" [ label=" ",color="blue",arrowhead="dot" ]; -"381" -> "118E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "177E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "178E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "179E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "180E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "181E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "182E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "183E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "184E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "185E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "186E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "187E" [ label=" ",color="blue",arrowhead="dot" ]; -"382" -> "188E" [ label=" ",color="blue",arrowhead="dot" ]; -"383" -> "730E" [ label=" ",color="blue",arrowhead="dot" ]; -"383" -> "732E" [ label=" ",color="blue",arrowhead="dot" ]; -"383" -> "741E" [ label=" ",color="blue",arrowhead="dot" ]; -"383" -> "765E" [ label=" ",color="blue",arrowhead="dot" ]; -"383" -> "796E" [ label=" ",color="blue",arrowhead="dot" ]; -"384" -> "726E" [ label=" ",color="blue",arrowhead="dot" ]; -"384" -> "728E" [ label=" ",color="blue",arrowhead="dot" ]; -"384" -> "742E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "328E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "496E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "594E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "622E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "754E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "755E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "756E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "757E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "758E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "759E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "760E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "761E" [ label=" ",color="blue",arrowhead="dot" ]; -"385" -> "762E" [ label=" ",color="blue",arrowhead="dot" ]; -"1E" -> "34E" [ color="purple",arrowhead="none" ]; -"2E" -> "35E" [ color="purple",arrowhead="none" ]; -"3E" -> "36E" [ color="purple",arrowhead="none" ]; -"4E" -> "37E" [ color="purple",arrowhead="none" ]; -"5E" -> "38E" [ color="purple",arrowhead="none" ]; -"6E" -> "39E" [ color="purple",arrowhead="none" ]; -"7E" -> "40E" [ color="purple",arrowhead="none" ]; -"9E" -> "41E" [ color="purple",arrowhead="none" ]; -"10E" -> "42E" [ color="purple",arrowhead="none" ]; -"11E" -> "43E" [ color="purple",arrowhead="none" ]; -"12E" -> "44E" [ color="purple",arrowhead="none" ]; -"13E" -> "45E" [ color="purple",arrowhead="none" ]; -"14E" -> "46E" [ color="purple",arrowhead="none" ]; -"15E" -> "47E" [ color="purple",arrowhead="none" ]; -"16E" -> "48E" [ color="purple",arrowhead="none" ]; -"49E" -> "17E" [ color="purple",arrowhead="none" ]; -"18E" -> "50E" [ color="purple",arrowhead="none" ]; -"19E" -> "51E" [ color="purple",arrowhead="none" ]; -"20E" -> "52E" [ color="purple",arrowhead="none" ]; -"21E" -> "53E" [ color="purple",arrowhead="none" ]; -"22E" -> "54E" [ color="purple",arrowhead="none" ]; -"23E" -> "55E" [ color="purple",arrowhead="none" ]; -"24E" -> "56E" [ color="purple",arrowhead="none" ]; -"25E" -> "57E" [ color="purple",arrowhead="none" ]; -"26E" -> "58E" [ color="purple",arrowhead="none" ]; -"27E" -> "59E" [ color="purple",arrowhead="none" ]; -"28E" -> "60E" [ color="purple",arrowhead="none" ]; -"29E" -> "61E" [ color="purple",arrowhead="none" ]; -"30E" -> "62E" [ color="purple",arrowhead="none" ]; -"31E" -> "63E" [ color="purple",arrowhead="none" ]; -"64E" -> "65E" [ color="purple",arrowhead="none" ]; -"66E" -> "8E" [ color="purple",arrowhead="none" ]; -"71E" -> "76E" [ color="purple",arrowhead="none" ]; -"67E" -> "72E" [ color="purple",arrowhead="none" ]; -"68E" -> "73E" [ color="purple",arrowhead="none" ]; -"69E" -> "74E" [ color="purple",arrowhead="none" ]; -"70E" -> "75E" [ color="purple",arrowhead="none" ]; -"81E" -> "92E" [ color="purple",arrowhead="none" ]; -"82E" -> "93E" [ color="purple",arrowhead="none" ]; -"83E" -> "94E" [ color="purple",arrowhead="none" ]; -"84E" -> "95E" [ color="purple",arrowhead="none" ]; -"85E" -> "96E" [ color="purple",arrowhead="none" ]; -"86E" -> "97E" [ color="purple",arrowhead="none" ]; -"87E" -> "98E" [ color="purple",arrowhead="none" ]; -"88E" -> "99E" [ color="purple",arrowhead="none" ]; -"89E" -> "100E" [ color="purple",arrowhead="none" ]; -"101E" -> "120E" [ color="purple",arrowhead="none" ]; -"102E" -> "121E" [ color="purple",arrowhead="none" ]; -"103E" -> "122E" [ color="purple",arrowhead="none" ]; -"104E" -> "123E" [ color="purple",arrowhead="none" ]; -"105E" -> "124E" [ color="purple",arrowhead="none" ]; -"106E" -> "125E" [ color="purple",arrowhead="none" ]; -"107E" -> "126E" [ color="purple",arrowhead="none" ]; -"108E" -> "127E" [ color="purple",arrowhead="none" ]; -"109E" -> "128E" [ color="purple",arrowhead="none" ]; -"110E" -> "129E" [ color="purple",arrowhead="none" ]; -"111E" -> "130E" [ color="purple",arrowhead="none" ]; -"112E" -> "131E" [ color="purple",arrowhead="none" ]; -"113E" -> "132E" [ color="purple",arrowhead="none" ]; -"114E" -> "133E" [ color="purple",arrowhead="none" ]; -"115E" -> "134E" [ color="purple",arrowhead="none" ]; -"116E" -> "135E" [ color="purple",arrowhead="none" ]; -"117E" -> "136E" [ color="purple",arrowhead="none" ]; -"118E" -> "137E" [ color="purple",arrowhead="none" ]; -"119E" -> "138E" [ color="purple",arrowhead="none" ]; -"139E" -> "151E" [ color="purple",arrowhead="none" ]; -"141E" -> "153E" [ color="purple",arrowhead="none" ]; -"142E" -> "154E" [ color="purple",arrowhead="none" ]; -"143E" -> "155E" [ color="purple",arrowhead="none" ]; -"144E" -> "156E" [ color="purple",arrowhead="none" ]; -"145E" -> "157E" [ color="purple",arrowhead="none" ]; -"146E" -> "158E" [ color="purple",arrowhead="none" ]; -"147E" -> "159E" [ color="purple",arrowhead="none" ]; -"148E" -> "160E" [ color="purple",arrowhead="none" ]; -"149E" -> "161E" [ color="purple",arrowhead="none" ]; -"150E" -> "162E" [ color="purple",arrowhead="none" ]; -"165E" -> "177E" [ color="purple",arrowhead="none" ]; -"166E" -> "178E" [ color="purple",arrowhead="none" ]; -"167E" -> "179E" [ color="purple",arrowhead="none" ]; -"168E" -> "180E" [ color="purple",arrowhead="none" ]; -"169E" -> "181E" [ color="purple",arrowhead="none" ]; -"170E" -> "182E" [ color="purple",arrowhead="none" ]; -"171E" -> "183E" [ color="purple",arrowhead="none" ]; -"172E" -> "184E" [ color="purple",arrowhead="none" ]; -"173E" -> "185E" [ color="purple",arrowhead="none" ]; -"174E" -> "186E" [ color="purple",arrowhead="none" ]; -"175E" -> "187E" [ color="purple",arrowhead="none" ]; -"176E" -> "188E" [ color="purple",arrowhead="none" ]; -"189E" -> "190E" [ color="purple",arrowhead="none" ]; -"191E" -> "192E" [ color="purple",arrowhead="none" ]; -"193E" -> "194E" [ color="purple",arrowhead="none" ]; -"195E" -> "196E" [ color="purple",arrowhead="none" ]; -"197E" -> "198E" [ color="purple",arrowhead="none" ]; -"199E" -> "200E" [ color="purple",arrowhead="none" ]; -"201E" -> "202E" [ color="purple",arrowhead="none" ]; -"203E" -> "204E" [ color="purple",arrowhead="none" ]; -"205E" -> "206E" [ color="purple",arrowhead="none" ]; -"207E" -> "208E" [ color="purple",arrowhead="none" ]; -"209E" -> "210E" [ color="purple",arrowhead="none" ]; -"412E" -> "211E" [ color="purple",arrowhead="none" ]; -"214E" -> "213E" [ color="purple",arrowhead="none" ]; -"216E" -> "215E" [ color="purple",arrowhead="none" ]; -"217E" -> "218E" [ color="purple",arrowhead="none" ]; -"219E" -> "220E" [ color="purple",arrowhead="none" ]; -"221E" -> "222E" [ color="purple",arrowhead="none" ]; -"223E" -> "224E" [ color="purple",arrowhead="none" ]; -"225E" -> "226E" [ color="purple",arrowhead="none" ]; -"227E" -> "228E" [ color="purple",arrowhead="none" ]; -"231E" -> "232E" [ color="purple",arrowhead="none" ]; -"233E" -> "234E" [ color="purple",arrowhead="none" ]; -"236E" -> "235E" [ color="purple",arrowhead="none" ]; -"237E" -> "238E" [ color="purple",arrowhead="none" ]; -"239E" -> "240E" [ color="purple",arrowhead="none" ]; -"241E" -> "242E" [ color="purple",arrowhead="none" ]; -"243E" -> "244E" [ color="purple",arrowhead="none" ]; -"245E" -> "246E" [ color="purple",arrowhead="none" ]; -"247E" -> "248E" [ color="purple",arrowhead="none" ]; -"249E" -> "250E" [ color="purple",arrowhead="none" ]; -"251E" -> "252E" [ color="purple",arrowhead="none" ]; -"253E" -> "254E" [ color="purple",arrowhead="none" ]; -"255E" -> "256E" [ color="purple",arrowhead="none" ]; -"257E" -> "258E" [ color="purple",arrowhead="none" ]; -"259E" -> "260E" [ color="purple",arrowhead="none" ]; -"261E" -> "262E" [ color="purple",arrowhead="none" ]; -"263E" -> "264E" [ color="purple",arrowhead="none" ]; -"265E" -> "266E" [ color="purple",arrowhead="none" ]; -"267E" -> "268E" [ color="purple",arrowhead="none" ]; -"269E" -> "270E" [ color="purple",arrowhead="none" ]; -"271E" -> "272E" [ color="purple",arrowhead="none" ]; -"273E" -> "274E" [ color="purple",arrowhead="none" ]; -"275E" -> "276E" [ color="purple",arrowhead="none" ]; -"278E" -> "277E" [ color="purple",arrowhead="none" ]; -"279E" -> "767E" [ color="purple",arrowhead="none" ]; -"281E" -> "282E" [ color="purple",arrowhead="none" ]; -"283E" -> "284E" [ color="purple",arrowhead="none" ]; -"285E" -> "286E" [ color="purple",arrowhead="none" ]; -"768E" -> "287E" [ color="purple",arrowhead="none" ]; -"289E" -> "290E" [ color="purple",arrowhead="none" ]; -"291E" -> "292E" [ color="purple",arrowhead="none" ]; -"293E" -> "294E" [ color="purple",arrowhead="none" ]; -"295E" -> "296E" [ color="purple",arrowhead="none" ]; -"297E" -> "298E" [ color="purple",arrowhead="none" ]; -"299E" -> "300E" [ color="purple",arrowhead="none" ]; -"301E" -> "302E" [ color="purple",arrowhead="none" ]; -"303E" -> "304E" [ color="purple",arrowhead="none" ]; -"305E" -> "306E" [ color="purple",arrowhead="none" ]; -"307E" -> "308E" [ color="purple",arrowhead="none" ]; -"309E" -> "310E" [ color="purple",arrowhead="none" ]; -"311E" -> "312E" [ color="purple",arrowhead="none" ]; -"313E" -> "314E" [ color="purple",arrowhead="none" ]; -"315E" -> "316E" [ color="purple",arrowhead="none" ]; -"317E" -> "318E" [ color="purple",arrowhead="none" ]; -"319E" -> "320E" [ color="purple",arrowhead="none" ]; -"321E" -> "322E" [ color="purple",arrowhead="none" ]; -"327E" -> "800E" [ color="purple",arrowhead="none" ]; -"329E" -> "330E" [ color="purple",arrowhead="none" ]; -"331E" -> "332E" [ color="purple",arrowhead="none" ]; -"333E" -> "334E" [ color="purple",arrowhead="none" ]; -"335E" -> "336E" [ color="purple",arrowhead="none" ]; -"337E" -> "338E" [ color="purple",arrowhead="none" ]; -"339E" -> "340E" [ color="purple",arrowhead="none" ]; -"341E" -> "342E" [ color="purple",arrowhead="none" ]; -"343E" -> "344E" [ color="purple",arrowhead="none" ]; -"345E" -> "346E" [ color="purple",arrowhead="none" ]; -"347E" -> "348E" [ color="purple",arrowhead="none" ]; -"349E" -> "350E" [ color="purple",arrowhead="none" ]; -"351E" -> "352E" [ color="purple",arrowhead="none" ]; -"353E" -> "354E" [ color="purple",arrowhead="none" ]; -"412E" -> "355E" [ color="purple",arrowhead="none" ]; -"357E" -> "358E" [ color="purple",arrowhead="none" ]; -"359E" -> "360E" [ color="purple",arrowhead="none" ]; -"361E" -> "362E" [ color="purple",arrowhead="none" ]; -"363E" -> "364E" [ color="purple",arrowhead="none" ]; -"365E" -> "366E" [ color="purple",arrowhead="none" ]; -"367E" -> "368E" [ color="purple",arrowhead="none" ]; -"369E" -> "370E" [ color="purple",arrowhead="none" ]; -"371E" -> "372E" [ color="purple",arrowhead="none" ]; -"373E" -> "374E" [ color="purple",arrowhead="none" ]; -"375E" -> "376E" [ color="purple",arrowhead="none" ]; -"377E" -> "378E" [ color="purple",arrowhead="none" ]; -"379E" -> "380E" [ color="purple",arrowhead="none" ]; -"381E" -> "382E" [ color="purple",arrowhead="none" ]; -"383E" -> "384E" [ color="purple",arrowhead="none" ]; -"385E" -> "386E" [ color="purple",arrowhead="none" ]; -"387E" -> "388E" [ color="purple",arrowhead="none" ]; -"389E" -> "390E" [ color="purple",arrowhead="none" ]; -"391E" -> "392E" [ color="purple",arrowhead="none" ]; -"393E" -> "394E" [ color="purple",arrowhead="none" ]; -"395E" -> "396E" [ color="purple",arrowhead="none" ]; -"397E" -> "398E" [ color="purple",arrowhead="none" ]; -"399E" -> "400E" [ color="purple",arrowhead="none" ]; -"402E" -> "401E" [ color="purple",arrowhead="none" ]; -"404E" -> "403E" [ color="purple",arrowhead="none" ]; -"406E" -> "405E" [ color="purple",arrowhead="none" ]; -"408E" -> "407E" [ color="purple",arrowhead="none" ]; -"236E" -> "409E" [ color="purple",arrowhead="none" ]; -"412E" -> "411E" [ color="purple",arrowhead="none" ]; -"412E" -> "413E" [ color="purple",arrowhead="none" ]; -"278E" -> "415E" [ color="purple",arrowhead="none" ]; -"417E" -> "418E" [ color="purple",arrowhead="none" ]; -"419E" -> "420E" [ color="purple",arrowhead="none" ]; -"421E" -> "422E" [ color="purple",arrowhead="none" ]; -"423E" -> "424E" [ color="purple",arrowhead="none" ]; -"425E" -> "426E" [ color="purple",arrowhead="none" ]; -"427E" -> "428E" [ color="purple",arrowhead="none" ]; -"431E" -> "432E" [ color="purple",arrowhead="none" ]; -"433E" -> "434E" [ color="purple",arrowhead="none" ]; -"435E" -> "436E" [ color="purple",arrowhead="none" ]; -"438E" -> "437E" [ color="purple",arrowhead="none" ]; -"439E" -> "440E" [ color="purple",arrowhead="none" ]; -"441E" -> "442E" [ color="purple",arrowhead="none" ]; -"443E" -> "444E" [ color="purple",arrowhead="none" ]; -"445E" -> "446E" [ color="purple",arrowhead="none" ]; -"448E" -> "447E" [ color="purple",arrowhead="none" ]; -"449E" -> "450E" [ color="purple",arrowhead="none" ]; -"451E" -> "452E" [ color="purple",arrowhead="none" ]; -"453E" -> "454E" [ color="purple",arrowhead="none" ]; -"455E" -> "456E" [ color="purple",arrowhead="none" ]; -"457E" -> "458E" [ color="purple",arrowhead="none" ]; -"459E" -> "460E" [ color="purple",arrowhead="none" ]; -"461E" -> "462E" [ color="purple",arrowhead="none" ]; -"236E" -> "463E" [ color="purple",arrowhead="none" ]; -"465E" -> "466E" [ color="purple",arrowhead="none" ]; -"467E" -> "468E" [ color="purple",arrowhead="none" ]; -"469E" -> "470E" [ color="purple",arrowhead="none" ]; -"471E" -> "472E" [ color="purple",arrowhead="none" ]; -"473E" -> "474E" [ color="purple",arrowhead="none" ]; -"476E" -> "475E" [ color="purple",arrowhead="none" ]; -"477E" -> "478E" [ color="purple",arrowhead="none" ]; -"479E" -> "358E" [ color="purple",arrowhead="none" ]; -"481E" -> "482E" [ color="purple",arrowhead="none" ]; -"483E" -> "484E" [ color="purple",arrowhead="none" ]; -"485E" -> "486E" [ color="purple",arrowhead="none" ]; -"487E" -> "488E" [ color="purple",arrowhead="none" ]; -"489E" -> "490E" [ color="purple",arrowhead="none" ]; -"491E" -> "492E" [ color="purple",arrowhead="none" ]; -"495E" -> "795E" [ color="purple",arrowhead="none" ]; -"499E" -> "500E" [ color="purple",arrowhead="none" ]; -"501E" -> "502E" [ color="purple",arrowhead="none" ]; -"504E" -> "503E" [ color="purple",arrowhead="none" ]; -"505E" -> "506E" [ color="purple",arrowhead="none" ]; -"507E" -> "508E" [ color="purple",arrowhead="none" ]; -"509E" -> "510E" [ color="purple",arrowhead="none" ]; -"412E" -> "511E" [ color="purple",arrowhead="none" ]; -"513E" -> "514E" [ color="purple",arrowhead="none" ]; -"515E" -> "516E" [ color="purple",arrowhead="none" ]; -"517E" -> "518E" [ color="purple",arrowhead="none" ]; -"519E" -> "520E" [ color="purple",arrowhead="none" ]; -"521E" -> "522E" [ color="purple",arrowhead="none" ]; -"523E" -> "524E" [ color="purple",arrowhead="none" ]; -"525E" -> "526E" [ color="purple",arrowhead="none" ]; -"527E" -> "528E" [ color="purple",arrowhead="none" ]; -"529E" -> "530E" [ color="purple",arrowhead="none" ]; -"531E" -> "532E" [ color="purple",arrowhead="none" ]; -"533E" -> "534E" [ color="purple",arrowhead="none" ]; -"535E" -> "536E" [ color="purple",arrowhead="none" ]; -"537E" -> "538E" [ color="purple",arrowhead="none" ]; -"539E" -> "540E" [ color="purple",arrowhead="none" ]; -"541E" -> "542E" [ color="purple",arrowhead="none" ]; -"543E" -> "544E" [ color="purple",arrowhead="none" ]; -"545E" -> "546E" [ color="purple",arrowhead="none" ]; -"547E" -> "548E" [ color="purple",arrowhead="none" ]; -"549E" -> "550E" [ color="purple",arrowhead="none" ]; -"551E" -> "552E" [ color="purple",arrowhead="none" ]; -"553E" -> "554E" [ color="purple",arrowhead="none" ]; -"555E" -> "556E" [ color="purple",arrowhead="none" ]; -"557E" -> "558E" [ color="purple",arrowhead="none" ]; -"278E" -> "559E" [ color="purple",arrowhead="none" ]; -"561E" -> "562E" [ color="purple",arrowhead="none" ]; -"563E" -> "564E" [ color="purple",arrowhead="none" ]; -"565E" -> "566E" [ color="purple",arrowhead="none" ]; -"567E" -> "568E" [ color="purple",arrowhead="none" ]; -"569E" -> "570E" [ color="purple",arrowhead="none" ]; -"571E" -> "572E" [ color="purple",arrowhead="none" ]; -"573E" -> "574E" [ color="purple",arrowhead="none" ]; -"575E" -> "576E" [ color="purple",arrowhead="none" ]; -"577E" -> "578E" [ color="purple",arrowhead="none" ]; -"579E" -> "580E" [ color="purple",arrowhead="none" ]; -"581E" -> "582E" [ color="purple",arrowhead="none" ]; -"583E" -> "584E" [ color="purple",arrowhead="none" ]; -"585E" -> "586E" [ color="purple",arrowhead="none" ]; -"587E" -> "588E" [ color="purple",arrowhead="none" ]; -"589E" -> "590E" [ color="purple",arrowhead="none" ]; -"593E" -> "594E" [ color="purple",arrowhead="none" ]; -"597E" -> "598E" [ color="purple",arrowhead="none" ]; -"599E" -> "600E" [ color="purple",arrowhead="none" ]; -"601E" -> "602E" [ color="purple",arrowhead="none" ]; -"603E" -> "604E" [ color="purple",arrowhead="none" ]; -"605E" -> "606E" [ color="purple",arrowhead="none" ]; -"607E" -> "608E" [ color="purple",arrowhead="none" ]; -"609E" -> "610E" [ color="purple",arrowhead="none" ]; -"611E" -> "612E" [ color="purple",arrowhead="none" ]; -"613E" -> "614E" [ color="purple",arrowhead="none" ]; -"615E" -> "358E" [ color="purple",arrowhead="none" ]; -"617E" -> "618E" [ color="purple",arrowhead="none" ]; -"619E" -> "620E" [ color="purple",arrowhead="none" ]; -"621E" -> "622E" [ color="purple",arrowhead="none" ]; -"623E" -> "624E" [ color="purple",arrowhead="none" ]; -"625E" -> "626E" [ color="purple",arrowhead="none" ]; -"627E" -> "628E" [ color="purple",arrowhead="none" ]; -"629E" -> "630E" [ color="purple",arrowhead="none" ]; -"631E" -> "632E" [ color="purple",arrowhead="none" ]; -"634E" -> "633E" [ color="purple",arrowhead="none" ]; -"635E" -> "636E" [ color="purple",arrowhead="none" ]; -"637E" -> "638E" [ color="purple",arrowhead="none" ]; -"639E" -> "640E" [ color="purple",arrowhead="none" ]; -"641E" -> "642E" [ color="purple",arrowhead="none" ]; -"643E" -> "644E" [ color="purple",arrowhead="none" ]; -"645E" -> "646E" [ color="purple",arrowhead="none" ]; -"647E" -> "648E" [ color="purple",arrowhead="none" ]; -"649E" -> "650E" [ color="purple",arrowhead="none" ]; -"651E" -> "652E" [ color="purple",arrowhead="none" ]; -"653E" -> "654E" [ color="purple",arrowhead="none" ]; -"655E" -> "656E" [ color="purple",arrowhead="none" ]; -"657E" -> "658E" [ color="purple",arrowhead="none" ]; -"659E" -> "660E" [ color="purple",arrowhead="none" ]; -"661E" -> "662E" [ color="purple",arrowhead="none" ]; -"663E" -> "664E" [ color="purple",arrowhead="none" ]; -"665E" -> "666E" [ color="purple",arrowhead="none" ]; -"667E" -> "668E" [ color="purple",arrowhead="none" ]; -"669E" -> "670E" [ color="purple",arrowhead="none" ]; -"671E" -> "672E" [ color="purple",arrowhead="none" ]; -"673E" -> "674E" [ color="purple",arrowhead="none" ]; -"675E" -> "676E" [ color="purple",arrowhead="none" ]; -"679E" -> "680E" [ color="purple",arrowhead="none" ]; -"681E" -> "682E" [ color="purple",arrowhead="none" ]; -"683E" -> "684E" [ color="purple",arrowhead="none" ]; -"685E" -> "686E" [ color="purple",arrowhead="none" ]; -"687E" -> "688E" [ color="purple",arrowhead="none" ]; -"689E" -> "690E" [ color="purple",arrowhead="none" ]; -"691E" -> "692E" [ color="purple",arrowhead="none" ]; -"693E" -> "694E" [ color="purple",arrowhead="none" ]; -"695E" -> "696E" [ color="purple",arrowhead="none" ]; -"697E" -> "698E" [ color="purple",arrowhead="none" ]; -"699E" -> "700E" [ color="purple",arrowhead="none" ]; -"703E" -> "704E" [ color="purple",arrowhead="none" ]; -"705E" -> "706E" [ color="purple",arrowhead="none" ]; -"709E" -> "710E" [ color="purple",arrowhead="none" ]; -"711E" -> "712E" [ color="purple",arrowhead="none" ]; -"713E" -> "714E" [ color="purple",arrowhead="none" ]; -"715E" -> "398E" [ color="purple",arrowhead="none" ]; -"717E" -> "718E" [ color="purple",arrowhead="none" ]; -"719E" -> "720E" [ color="purple",arrowhead="none" ]; -"721E" -> "722E" [ color="purple",arrowhead="none" ]; -"725E" -> "726E" [ color="purple",arrowhead="none" ]; -"727E" -> "728E" [ color="purple",arrowhead="none" ]; -"729E" -> "730E" [ color="purple",arrowhead="none" ]; -"731E" -> "732E" [ color="purple",arrowhead="none" ]; -"741E" -> "743E" [ color="purple",arrowhead="none" ]; -"742E" -> "744E" [ color="purple",arrowhead="none" ]; -"745E" -> "754E" [ color="purple",arrowhead="none" ]; -"746E" -> "755E" [ color="purple",arrowhead="none" ]; -"747E" -> "756E" [ color="purple",arrowhead="none" ]; -"748E" -> "757E" [ color="purple",arrowhead="none" ]; -"749E" -> "758E" [ color="purple",arrowhead="none" ]; -"750E" -> "759E" [ color="purple",arrowhead="none" ]; -"751E" -> "760E" [ color="purple",arrowhead="none" ]; -"752E" -> "761E" [ color="purple",arrowhead="none" ]; -"753E" -> "762E" [ color="purple",arrowhead="none" ]; -"763E" -> "764E" [ color="purple",arrowhead="none" ]; -"765E" -> "766E" [ color="purple",arrowhead="none" ]; -"770E" -> "783E" [ color="purple",arrowhead="none" ]; -"770E" -> "784E" [ color="purple",arrowhead="none" ]; -"769E" -> "785E" [ color="purple",arrowhead="none" ]; -"769E" -> "786E" [ color="purple",arrowhead="none" ]; -"769E" -> "787E" [ color="purple",arrowhead="none" ]; -"770E" -> "788E" [ color="purple",arrowhead="none" ]; -"770E" -> "789E" [ color="purple",arrowhead="none" ]; -"769E" -> "790E" [ color="purple",arrowhead="none" ]; -"770E" -> "791E" [ color="purple",arrowhead="none" ]; -"769E" -> "792E" [ color="purple",arrowhead="none" ]; -"793E" -> "769E" [ color="purple",arrowhead="none" ]; -"769E" -> "784E" [ color="purple",arrowhead="none" ]; -"770E" -> "785E" [ color="purple",arrowhead="none" ]; -"788E" -> "787E" [ color="purple",arrowhead="none" ]; -"770E" -> "792E" [ color="purple",arrowhead="none" ]; -"798E" -> "799E" [ color="purple",arrowhead="none" ]; -"796E" -> "797E" [ color="purple",arrowhead="none" ]; -"793E" -> "789E" [ color="purple",arrowhead="none" ]; -"783E" -> "787E" [ color="purple",arrowhead="none" ]; -"784E" -> "792E" [ color="purple",arrowhead="none" ]; -"787E" -> "789E" [ color="purple",arrowhead="none" ]; -"769E" -> "791E" [ color="purple",arrowhead="none" ]; -"802E" -> "801E" [ color="purple",arrowhead="none" ]; -} diff --git a/dot/6.dot b/dot/6.dot deleted file mode 100644 index 0189738..0000000 --- a/dot/6.dot +++ /dev/null @@ -1,2140 +0,0 @@ -/* contributed by Sancho Lerena, http://pandorafms.org - -About the graph: this is an automated network map generated with Pandora -FMS, this map is a visual representation of the network discovery done by -the recon server, which sweeps the network, and identify hosts in a network -and the full chain of hosts in the route to discovered networks. - -command: - -twopi -Tcmapx -onetworkmap_twopi_1.map -Tpng -onetworkmap_twopi.png networkmap_twopi.gv.txt - -*/ - -graph networkmap { labeljust=l; margin=0; ratio=fill;root=0;size="8,5.4";300 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    109.217.106.212.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=300", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=300"]; - 619 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    192.36.144.230
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=619", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=619"]; - 686 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.0.255
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=686", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=686"]; - 620 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.0.53
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=620", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=620"]; - 692 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=692", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=692"]; - 699 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.10
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=699", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=699"]; - 700 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.12
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=700", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=700"]; - 701 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.13
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=701", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=701"]; - 702 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=702", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=702"]; - 703 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.15
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=703", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=703"]; - 704 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.16
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=704", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=704"]; - 705 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=705", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=705"]; - 706 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.18
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=706", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=706"]; - 707 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.19
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=707", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=707"]; - 694 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.2
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=694", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=694"]; - 708 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.20
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=708", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=708"]; - 709 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.21
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=709", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=709"]; - 710 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.22
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=710", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=710"]; - 711 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.23
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=711", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=711"]; - 712 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.24
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=712", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=712"]; - 791 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.240
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=791", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=791"]; - 792 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.253
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=792", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=792"]; - 713 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.26
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=713", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=713"]; - 714 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.27
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=714", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=714"]; - 715 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.28
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=715", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=715"]; - 716 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.29
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=716", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=716"]; - 695 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.3
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=695", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=695"]; - 717 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.30
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=717", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=717"]; - 718 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.31
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=718", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=718"]; - 719 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.36
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=719", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=719"]; - 696 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.4
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=696", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=696"]; - 697 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.7
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=697", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=697"]; - 698 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.1.9
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=698", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=698"]; - 793 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=793", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=793"]; - 798 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.10
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=798", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=798"]; - 799 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.12
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=799", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=799"]; - 800 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.13
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=800", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=800"]; - 801 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=801", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=801"]; - 802 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.15
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=802", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=802"]; - 803 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.16
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=803", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=803"]; - 804 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=804", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=804"]; - 805 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.18
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=805", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=805"]; - 806 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.19
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=806", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=806"]; - 794 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.2
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=794", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=794"]; - 807 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.20
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=807", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=807"]; - 795 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.5
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=795", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=795"]; - 796 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.6
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=796", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=796"]; - 797 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.2.7
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=797", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=797"]; - 813 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    194.0.3.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=813", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=813"]; - 690 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.187.255.152
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=690", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=690"]; - 689 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.187.255.156
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=689", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=689"]; - 691 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.187.255.161
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=691", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=691"]; - 533 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.66.224.76
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=533", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=533"]; - 538 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.66.224.76
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=538", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=538"]; - 570 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.66.225.69
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=570", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=570"]; - 616 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    195.69.119.172
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=616", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=616"]; - 581 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    204.15.20.35
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=581", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=581"]; - 647 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    204.15.22.245
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=647", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=647"]; - 577 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    204.15.23.111
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=577", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=577"]; - 557 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.100
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=557", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=557"]; - 558 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.101
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=558", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=558"]; - 560 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.102
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=560", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=560"]; - 562 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.104
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=562", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=562"]; - 568 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.109
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=568", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=568"]; - 425 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=425", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=425"]; - 426 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.16
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=426", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=426"]; - 427 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.18
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=427", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=427"]; - 428 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.19
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=428", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=428"]; - 430 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.27
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=430", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=430"]; - 431 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.32
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=431", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=431"]; - 432 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.33
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=432", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=432"]; - 433 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.34
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=433", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=433"]; - 434 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.35
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=434", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=434"]; - 435 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.36
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=435", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=435"]; - 436 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.37
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=436", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=436"]; - 437 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.38
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=437", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=437"]; - 445 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.39
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=445", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=445"]; - 419 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.4
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=419", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=419"]; - 447 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.40
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=447", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=447"]; - 449 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.41
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=449", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=449"]; - 451 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.42
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=451", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=451"]; - 452 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.43
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=452", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=452"]; - 454 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.44
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=454", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=454"]; - 456 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.45
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=456", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=456"]; - 458 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.46
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=458", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=458"]; - 460 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.47
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=460", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=460"]; - 462 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.48
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=462", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=462"]; - 464 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.49
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=464", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=464"]; - 422 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.5
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=422", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=422"]; - 466 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.50
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=466", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=466"]; - 468 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.51
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=468", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=468"]; - 470 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.52
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=470", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=470"]; - 472 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.53
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=472", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=472"]; - 474 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.54
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=474", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=474"]; - 476 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.56
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=476", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=476"]; - 478 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.57
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=478", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=478"]; - 479 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.58
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=479", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=479"]; - 481 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.59
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=481", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=481"]; - 423 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.6
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=423", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=423"]; - 483 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.60
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=483", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=483"]; - 484 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.61
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=484", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=484"]; - 485 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.62
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=485", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=485"]; - 487 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.63
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=487", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=487"]; - 489 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.64
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=489", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=489"]; - 491 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.65
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=491", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=491"]; - 493 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.66
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=493", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=493"]; - 496 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.68
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=496", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=496"]; - 498 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.69
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=498", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=498"]; - 502 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.72
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=502", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=502"]; - 504 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.73
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=504", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=504"]; - 505 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.74
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=505", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=505"]; - 507 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.75
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=507", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=507"]; - 509 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.76
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=509", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=509"]; - 511 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.77
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=511", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=511"]; - 513 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.78
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=513", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=513"]; - 515 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.79
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=515", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=515"]; - 517 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.81
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=517", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=517"]; - 518 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.82
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=518", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=518"]; - 519 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.83
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=519", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=519"]; - 521 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.84
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=521", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=521"]; - 523 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.85
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=523", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=523"]; - 525 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.86
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=525", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=525"]; - 527 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.87
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=527", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=527"]; - 529 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.88
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=529", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=529"]; - 531 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.89
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=531", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=531"]; - 542 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.91
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=542", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=542"]; - 544 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.93
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=544", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=544"]; - 547 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.95
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=547", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=547"]; - 549 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.96
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=549", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=549"]; - 551 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.97
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=551", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=551"]; - 553 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.98
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=553", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=553"]; - 555 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.229.99
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=555", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=555"]; - 421 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.243.73
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=421", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=421"]; - 418 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.243.77
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=418", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=418"]; - 429 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.243.81
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=429", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=429"]; - 424 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.243.85
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=424", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=424"]; - 415 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.251.200
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=415", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=415"]; - 420 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    209.85.252.83
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=420", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=420"]; - 416 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    216.239.43.233
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=416", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=416"]; - 414 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    216.239.49.196
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=414", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=414"]; - 417 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    216.239.49.45
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=417", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=417"]; - 808 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    62.40.112.122
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=808", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=808"]; - 809 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    62.40.112.206
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=809", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=809"]; - 810 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    62.40.125.158
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=810", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=810"]; - 534 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.27.149
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=534", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=534"]; - 539 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.27.149
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=539", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=539"]; - 536 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.29.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=536", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=536"]; - 541 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.29.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=541", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=541"]; - 535 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.31.186
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=535", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=535"]; - 540 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    64.125.31.186
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=540", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=540"]; - 573 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=573", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=573"]; - 580 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.11
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=580", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=580"]; - 583 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.13
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=583", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=583"]; - 585 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=585", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=585"]; - 587 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.15
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=587", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=587"]; - 612 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.150
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=612", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=612"]; - 613 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.151
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=613", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=613"]; - 614 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.152
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=614", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=614"]; - 615 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.153
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=615", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=615"]; - 588 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=588", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=588"]; - 590 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.18
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=590", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=590"]; - 592 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.19
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=592", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=592"]; - 574 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.2
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=574", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=574"]; - 593 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.21
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=593", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=593"]; - 594 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.22
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=594", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=594"]; - 595 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.23
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=595", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=595"]; - 621 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.231
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=621", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=621"]; - 622 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.232
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=622", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=622"]; - 623 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.233
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=623", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=623"]; - 624 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.234
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=624", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=624"]; - 625 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.244
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=625", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=625"]; - 626 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.245
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=626", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=626"]; - 627 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.246
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=627", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=627"]; - 628 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.247
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=628", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=628"]; - 629 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.248
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=629", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=629"]; - 630 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.249
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=630", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=630"]; - 596 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.25
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=596", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=596"]; - 631 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.250
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=631", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=631"]; - 632 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.251
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=632", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=632"]; - 633 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.252
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=633", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=633"]; - 634 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.253
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=634", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=634"]; - 635 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.254
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=635", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=635"]; - 597 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.26
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=597", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=597"]; - 599 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.27
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=599", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=599"]; - 600 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.28
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=600", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=600"]; - 601 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.29
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=601", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=601"]; - 602 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.30
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=602", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=602"]; - 604 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.31
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=604", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=604"]; - 605 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.32
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=605", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=605"]; - 606 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.33
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=606", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=606"]; - 607 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.34
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=607", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=607"]; - 608 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.35
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=608", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=608"]; - 609 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.36
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=609", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=609"]; - 610 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.37
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=610", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=610"]; - 611 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.38
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=611", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=611"]; - 576 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.5
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=576", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=576"]; - 578 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.153.6
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=578", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=578"]; - 636 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.33
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=636", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=636"]; - 638 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.34
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=638", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=638"]; - 639 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.35
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=639", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=639"]; - 640 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.36
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=640", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=640"]; - 641 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.49
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=641", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=641"]; - 643 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.50
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=643", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=643"]; - 644 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.51
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=644", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=644"]; - 645 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.154.52
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=645", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=645"]; - 646 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=646", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=646"]; - 654 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.10
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=654", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=654"]; - 720 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.105
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=720", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=720"]; - 721 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.106
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=721", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=721"]; - 656 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.11
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=656", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=656"]; - 723 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.116
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=723", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=723"]; - 724 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.117
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=724", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=724"]; - 725 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.118
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=725", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=725"]; - 726 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.119
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=726", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=726"]; - 658 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.12
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=658", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=658"]; - 727 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.120
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=727", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=727"]; - 728 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.121
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=728", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=728"]; - 729 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.122
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=729", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=729"]; - 730 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.123
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=730", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=730"]; - 731 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.124
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=731", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=731"]; - 732 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.125
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=732", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=732"]; - 733 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.126
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=733", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=733"]; - 734 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.129
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=734", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=734"]; - 660 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.13
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=660", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=660"]; - 735 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.130
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=735", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=735"]; - 736 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.133
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=736", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=736"]; - 737 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.134
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=737", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=737"]; - 738 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.135
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=738", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=738"]; - 739 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.136
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=739", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=739"]; - 740 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.137
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=740", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=740"]; - 741 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.138
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=741", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=741"]; - 742 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.139
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=742", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=742"]; - 661 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=661", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=661"]; - 743 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.140
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=743", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=743"]; - 744 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.141
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=744", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=744"]; - 745 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.142
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=745", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=745"]; - 746 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.143
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=746", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=746"]; - 747 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.144
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=747", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=747"]; - 748 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.145
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=748", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=748"]; - 749 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.146
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=749", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=749"]; - 750 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.147
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=750", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=750"]; - 751 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.148
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=751", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=751"]; - 752 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.149
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=752", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=752"]; - 662 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.15
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=662", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=662"]; - 753 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.150
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=753", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=753"]; - 754 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.151
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=754", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=754"]; - 755 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.152
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=755", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=755"]; - 756 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.153
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=756", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=756"]; - 757 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.154
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=757", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=757"]; - 758 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.155
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=758", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=758"]; - 759 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.156
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=759", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=759"]; - 760 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.157
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=760", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=760"]; - 761 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.158
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=761", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=761"]; - 762 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.159
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=762", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=762"]; - 664 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.16
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=664", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=664"]; - 763 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.160
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=763", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=763"]; - 764 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.161
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=764", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=764"]; - 765 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.162
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=765", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=765"]; - 766 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.163
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=766", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=766"]; - 767 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.164
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=767", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=767"]; - 768 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.165
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=768", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=768"]; - 769 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.166
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=769", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=769"]; - 770 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.167
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=770", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=770"]; - 771 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.168
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=771", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=771"]; - 772 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.169
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=772", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=772"]; - 665 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.17
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=665", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=665"]; - 773 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.170
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=773", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=773"]; - 774 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.171
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=774", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=774"]; - 775 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.172
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=775", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=775"]; - 776 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.173
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=776", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=776"]; - 777 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.174
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=777", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=777"]; - 778 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.175
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=778", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=778"]; - 779 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.176
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=779", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=779"]; - 780 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.177
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=780", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=780"]; - 781 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.178
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=781", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=781"]; - 782 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.179
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=782", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=782"]; - 666 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.18
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=666", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=666"]; - 783 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.180
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=783", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=783"]; - 784 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.181
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=784", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=784"]; - 785 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.182
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=785", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=785"]; - 786 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.183
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=786", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=786"]; - 667 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.19
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=667", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=667"]; - 649 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.2
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=649", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=649"]; - 668 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.20
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=668", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=668"]; - 669 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.21
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=669", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=669"]; - 670 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.22
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=670", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=670"]; - 671 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.23
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=671", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=671"]; - 787 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.234
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=787", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=787"]; - 672 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.24
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=672", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=672"]; - 788 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.241
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=788", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=788"]; - 789 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.242
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=789", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=789"]; - 790 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.243
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=790", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=790"]; - 673 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.25
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=673", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=673"]; - 674 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.26
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=674", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=674"]; - 676 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.27
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=676", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=676"]; - 677 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.28
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=677", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=677"]; - 678 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.29
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=678", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=678"]; - 679 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.43
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=679", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=679"]; - 680 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.44
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=680", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=680"]; - 650 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.5
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=650", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=650"]; - 681 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.52
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=681", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=681"]; - 682 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.53
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=682", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=682"]; - 683 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.54
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=683", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=683"]; - 684 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.55
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=684", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=684"]; - 685 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.56
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=685", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=685"]; - 652 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.6
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=652", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=652"]; - 693 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.220.155.63
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=693", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=693"]; - 438 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.33.201.221
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=438", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=438"]; - 439 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    66.33.201.66
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=439", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=439"]; - 359 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=359", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=359"]; - 366 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.10
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=366", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=366"]; - 516 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.101
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=516", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=516"]; - 520 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.102
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=520", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=520"]; - 522 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.103
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=522", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=522"]; - 524 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.104
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=524", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=524"]; - 526 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.105
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=526", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=526"]; - 528 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.106
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=528", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=528"]; - 530 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.107
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=530", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=530"]; - 532 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.108
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=532", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=532"]; - 537 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.109
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=537", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=537"]; - 367 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.11
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=367", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=367"]; - 543 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.110
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=543", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=543"]; - 545 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.111
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=545", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=545"]; - 546 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.112
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=546", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=546"]; - 548 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.113
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=548", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=548"]; - 550 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.114
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=550", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=550"]; - 391 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.36
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=391", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=391"]; - 392 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.37
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=392", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=392"]; - 393 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.38
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=393", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=393"]; - 394 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.39
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=394", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=394"]; - 360 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.4
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=360", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=360"]; - 395 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.40
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=395", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=395"]; - 396 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.41
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=396", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=396"]; - 397 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.42
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=397", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=397"]; - 398 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.44
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=398", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=398"]; - 399 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.45
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=399", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=399"]; - 400 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.163.176.46
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=400", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=400"]; - 301 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    69.216.106.212.s
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=301", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=301"]; - 657 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.193
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=657", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=657"]; - 651 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.215
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=651", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=651"]; - 655 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.217
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=655", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=655"]; - 659 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.219
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=659", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=659"]; - 663 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.221
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=663", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=663"]; - 653 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.223
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=653", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=653"]; - 722 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.225
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=722", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=722"]; - 675 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.227
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=675", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=675"]; - 579 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.237
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=579", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=579"]; - 591 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.239
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=591", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=591"]; - 603 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.245
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=603", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=603"]; - 589 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.247
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=589", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=589"]; - 575 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.77
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=575", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=575"]; - 572 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.76.79
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=572", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=572"]; - 637 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.142
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=637", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=637"]; - 642 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.144
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=642", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=642"]; - 582 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.77
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=582", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=582"]; - 584 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.79
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=584", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=584"]; - 586 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.81
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=586", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=586"]; - 598 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.77.83
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=598", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=598"]; - 571 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.78.182
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=571", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=571"]; - 648 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    74.119.78.83
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=648", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=648"]; - 618 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    77.72.228.14
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=618", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=618"]; - 617 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    77.72.228.45
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=617", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=617"]; - 688 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    84.233.213.222
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=688", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=688"]; - 687 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    84.233.213.41
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=687", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=687"]; - 812 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    85.254.196.210
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=812", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=812"]; - 811 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    85.254.196.237
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=811", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=811"]; - 331 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.31
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=331", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=331"]; - 332 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.32
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=332", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=332"]; - 333 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.33
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=333", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=333"]; - 334 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.34
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=334", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=334"]; - 335 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.35
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=335", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=335"]; - 336 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.38
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=336", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=336"]; - 337 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.39
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=337", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=337"]; - 338 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.40
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=338", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=338"]; - 339 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.41
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=339", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=339"]; - 340 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.42
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=340", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=340"]; - 341 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.43
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=341", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=341"]; - 342 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.44
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=342", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=342"]; - 343 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.45
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=343", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=343"]; - 344 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.46
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=344", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=344"]; - 345 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.47
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=345", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=345"]; - 346 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.48
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=346", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=346"]; - 347 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.49
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=347", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=347"]; - 348 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.50
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=348", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=348"]; - 349 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.51
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=349", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=349"]; - 350 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.52
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=350", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=350"]; - 351 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.53
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=351", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=351"]; - 352 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.56
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=352", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=352"]; - 353 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.57
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=353", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=353"]; - 354 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.58
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=354", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=354"]; - 355 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.59
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=355", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=355"]; - 356 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.60
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=356", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=356"]; - 357 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.61
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=357", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=357"]; - 358 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    87.248.112.62
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=358", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=358"]; - 306 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    unknown-66-196-6
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=306", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=306"]; - 319 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    unknown-87-248-1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=319", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=319"]; - 320 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    unknown-87-248-1
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=320", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=320"]; - 304 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    ae-1.msr1.ird.ya
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=304", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=304"]; - 307 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    ae-2.msr2.ird.ya
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=307", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=307"]; - 316 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    fe.gsp.search.vi
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=316", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=316"]; - 302 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    ge-1-1-0.pat1.th
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=302", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=302"]; - 305 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    ha1.vl-220.bas-b
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=305", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=305"]; - 308 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    ha2.vl-220.bas-b
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=308", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=308"]; - 1 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    metafora
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=1", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=1"]; - 2 [ color="#FF1D1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    metafora.artica.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=2", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=2"]; - 325 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    p1.movies.ird.ya
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=325", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=325"]; - 323 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    p1.tv.ird.yahoo.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=323", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=323"]; - 330 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    p2.movies.ird.ya
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=330", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=330"]; - 329 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    p2.tv.ird.yahoo.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=329", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=329"]; - 321 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    p4.tv.ird.yahoo.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=321", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=321"]; - 322 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    qa-eu.ent.ird.ya
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=322", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=322"]; - 315 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    rd.gsp.search.vi
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=315", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=315"]; - 326 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    rd01.gsp.search.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=326", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=326"]; - 327 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    rd02.gsp.search.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=327", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=327"]; - 328 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    rd03.gsp.search.
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=328", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=328"]; - 312 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    si-b34.vrrp.vl22
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=312", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=312"]; - 303 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    so-0-0-0.pat1.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=303", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=303"]; - 314 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    te-7-4.bas-b1.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=314", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=314"]; - 317 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    te-7-4.bas-b2.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=317", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=317"]; - 324 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    te-8-4.bas-b1.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=324", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=324"]; - 311 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    te-8-4.bas-b2.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=311", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=311"]; - 309 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    vl-220.bas-b1.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=309", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=309"]; - 310 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    vl-220.bas-b2.ir
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=310", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=310"]; - 313 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    yts1.yql.ird.yah
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=313", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=313"]; - 318 [ color="#8DFF1D", fontsize=12, style="filled", fixedsize=true, width=0.40, height=0.40, label=< -
    z6po-feeder.sear
    >, - shape="doublecircle", URL="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=318", - tooltip="ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=318"]; - 619 -- 618[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=619&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];686 -- 618[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=686&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];620 -- 619[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=620&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];692 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=692&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];699 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=699&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];700 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=700&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];701 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=701&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];702 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=702&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];703 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=703&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];704 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=704&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];705 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=705&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];706 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=706&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];707 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=707&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];694 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=694&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];708 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=708&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];709 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=709&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];710 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=710&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];711 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=711&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];712 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=712&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];791 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=791&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];792 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=792&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];713 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=713&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];714 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=714&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];715 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=715&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];716 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=716&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];695 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=695&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];717 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=717&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];718 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=718&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];719 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=719&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];696 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=696&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];697 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=697&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];698 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=698&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];793 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=793&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];798 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=798&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];799 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=799&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];800 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=800&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];801 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=801&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];802 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=802&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];803 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=803&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];804 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=804&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];805 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=805&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];806 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=806&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];794 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=794&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];807 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=807&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];795 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=795&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];796 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=796&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];797 -- 691[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=797&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];813 -- 812[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=813&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];690 -- 689[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=690&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];689 -- 688[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=689&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];691 -- 690[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=691&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];533 -- 301[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=533&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];538 -- 301[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=538&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];570 -- 301[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=570&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];581 -- 571[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=581&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];647 -- 570[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=647&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];577 -- 571[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=577&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];557 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=557&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];558 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=558&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];560 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=560&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];562 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=562&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];568 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=568&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];425 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=425&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];426 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=426&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];427 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=427&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];428 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=428&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];430 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=430&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];431 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=431&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];432 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=432&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];433 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=433&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];434 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=434&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];435 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=435&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];436 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=436&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];437 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=437&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];445 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=445&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];419 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=419&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];447 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=447&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];449 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=449&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];451 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=451&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];452 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=452&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];454 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=454&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];456 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=456&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];458 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=458&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];460 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=460&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];462 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=462&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];464 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=464&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];422 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=422&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];466 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=466&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];468 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=468&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];470 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=470&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];472 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=472&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];474 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=474&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];476 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=476&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];478 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=478&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];479 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=479&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];481 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=481&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];423 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=423&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];483 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=483&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];484 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=484&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];485 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=485&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];487 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=487&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];489 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=489&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];491 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=491&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];493 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=493&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];496 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=496&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];498 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=498&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];502 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=502&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];504 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=504&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];505 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=505&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];507 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=507&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];509 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=509&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];511 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=511&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];513 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=513&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];515 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=515&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];517 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=517&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];518 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=518&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];519 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=519&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];521 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=521&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];523 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=523&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];525 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=525&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];527 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=527&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];529 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=529&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];531 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=531&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];542 -- 541[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=542&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];544 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=544&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];547 -- 429[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=547&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];549 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=549&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];551 -- 424[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=551&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];553 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=553&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];555 -- 418[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=555&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];421 -- 420[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=421&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];418 -- 417[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=418&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];429 -- 417[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=429&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];424 -- 420[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=424&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];415 -- 414[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=415&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];420 -- 416[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=420&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];416 -- 415[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=416&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];417 -- 416[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=417&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];809 -- 808[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=809&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];810 -- 809[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=810&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];534 -- 533[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=534&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];539 -- 538[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=539&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];536 -- 535[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=536&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];541 -- 540[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=541&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];535 -- 534[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=535&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];540 -- 539[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=540&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];573 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=573&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];580 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=580&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];583 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=583&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];585 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=585&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];587 -- 586[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=587&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];612 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=612&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];613 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=613&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];614 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=614&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];615 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=615&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];588 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=588&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];590 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=590&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];592 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=592&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];574 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=574&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];593 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=593&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];594 -- 586[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=594&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];595 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=595&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];621 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=621&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];622 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=622&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];623 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=623&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];624 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=624&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];625 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=625&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];626 -- 598[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=626&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];627 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=627&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];628 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=628&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];629 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=629&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];630 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=630&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];596 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=596&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];631 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=631&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];632 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=632&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];633 -- 598[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=633&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];634 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=634&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];635 -- 586[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=635&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];597 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=597&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];599 -- 598[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=599&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];600 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=600&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];601 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=601&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];602 -- 584[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=602&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];604 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=604&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];605 -- 589[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=605&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];606 -- 603[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=606&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];607 -- 579[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=607&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];608 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=608&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];609 -- 591[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=609&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];610 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=610&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];611 -- 582[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=611&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];576 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=576&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];578 -- 577[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=578&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];636 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=636&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];638 -- 637[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=638&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];639 -- 637[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=639&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];640 -- 637[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=640&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];641 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=641&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];643 -- 642[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=643&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];644 -- 642[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=644&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];645 -- 642[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=645&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];646 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=646&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];654 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=654&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];720 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=720&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];721 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=721&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];656 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=656&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];723 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=723&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];724 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=724&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];725 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=725&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];726 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=726&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];658 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=658&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];727 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=727&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];728 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=728&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];729 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=729&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];730 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=730&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];731 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=731&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];732 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=732&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];733 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=733&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];734 -- 648[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=734&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];660 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=660&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];735 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=735&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];736 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=736&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];737 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=737&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];738 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=738&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];739 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=739&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];740 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=740&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];741 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=741&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];742 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=742&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];661 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=661&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];743 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=743&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];744 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=744&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];745 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=745&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];746 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=746&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];747 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=747&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];748 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=748&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];749 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=749&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];750 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=750&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];751 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=751&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];752 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=752&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];662 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=662&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];753 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=753&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];754 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=754&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];755 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=755&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];756 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=756&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];757 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=757&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];758 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=758&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];759 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=759&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];760 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=760&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];761 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=761&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];762 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=762&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];664 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=664&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];763 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=763&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];764 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=764&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];765 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=765&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];766 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=766&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];767 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=767&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];768 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=768&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];769 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=769&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];770 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=770&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];771 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=771&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];772 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=772&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];665 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=665&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];773 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=773&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];774 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=774&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];775 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=775&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];776 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=776&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];777 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=777&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];778 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=778&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];779 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=779&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];780 -- 722[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=780&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];781 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=781&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];782 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=782&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];666 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=666&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];783 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=783&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];784 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=784&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];785 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=785&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];786 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=786&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];667 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=667&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];649 -- 648[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=649&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];668 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=668&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];669 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=669&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];670 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=670&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];671 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=671&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];787 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=787&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];672 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=672&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];788 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=788&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];789 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=789&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];790 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=790&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];673 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=673&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];674 -- 657[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=674&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];676 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=676&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];677 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=677&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];678 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=678&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];679 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=679&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];680 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=680&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];650 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=650&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];681 -- 653[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=681&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];682 -- 659[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=682&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];683 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=683&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];684 -- 675[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=684&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];685 -- 655[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=685&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];652 -- 651[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=652&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];693 -- 663[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=693&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];439 -- 359[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=439&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];359 -- 438[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=359&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];366 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=366&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];516 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=516&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];522 -- 421[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=522&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];524 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=524&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];526 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=526&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];528 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=528&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];530 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=530&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];532 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=532&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];537 -- 536[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=537&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];367 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=367&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];543 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=543&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];545 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=545&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];546 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=546&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];548 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=548&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];550 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=550&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];391 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=391&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];392 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=392&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];393 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=393&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];394 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=394&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];360 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=360&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];395 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=395&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];396 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=396&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];397 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=397&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];398 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=398&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];399 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=399&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];400 -- 439[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=400&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];301 -- 300[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=301&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];657 -- 581[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=657&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];651 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=651&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];655 -- 577[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=655&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];659 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=659&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];663 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=663&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];653 -- 648[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=653&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];722 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=722&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];675 -- 577[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=675&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];579 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=579&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];591 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=591&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];603 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=603&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];589 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=589&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];575 -- 571[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=575&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];572 -- 571[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=572&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];637 -- 575[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=637&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];642 -- 572[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=642&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];582 -- 581[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=582&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];584 -- 577[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=584&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];586 -- 581[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=586&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];598 -- 577[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=598&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];571 -- 570[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=571&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];648 -- 647[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=648&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];618 -- 617[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=618&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];617 -- 616[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=617&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];688 -- 687[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=688&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];812 -- 811[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=812&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];811 -- 810[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=811&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];331 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=331&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];332 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=332&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];333 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=333&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];334 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=334&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];335 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=335&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];336 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=336&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];337 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=337&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];338 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=338&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];339 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=339&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];340 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=340&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];341 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=341&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];342 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=342&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];343 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=343&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];344 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=344&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];345 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=345&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];346 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=346&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];347 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=347&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];348 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=348&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];349 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=349&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];350 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=350&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];351 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=351&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];352 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=352&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];353 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=353&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];354 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=354&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];355 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=355&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];356 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=356&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];357 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=357&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];358 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=358&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];306 -- 302[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=306&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];319 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=319&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];320 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=320&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];304 -- 303[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=304&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];307 -- 306[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=307&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];316 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=316&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];302 -- 301[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=302&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];305 -- 304[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=305&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];308 -- 307[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=308&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];325 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=325&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];323 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=323&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];330 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=330&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];329 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=329&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];321 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=321&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];322 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=322&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];315 -- 314[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=315&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];326 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=326&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];327 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=327&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];328 -- 324[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=328&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];312 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=312&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];303 -- 302[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=303&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];314 -- 307[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=314&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];317 -- 307[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=317&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];324 -- 304[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=324&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];311 -- 304[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=311&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];309 -- 307[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=309&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];310 -- 307[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=310&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];313 -- 311[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=313&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];318 -- 317[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=318&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 [ color="#364D1F", fontsize=12, style="filled", fixedsize=true, width=0.8, height=0.6, label=<
    Pandora FMS
    >, - shape="ellipse", URL="index.php?sec=estado&sec2=operation/agentes/group_view" ];0 -- 300[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 616[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 414[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 808[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 438[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 520[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 687[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 1[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];0 -- 2[color="#BDBDBD", headclip=false, tailclip=false, - edgeURL="index.php?sec=estado&sec2=operation/agentes/networkmap&tab=topology&recenter_networkmap=1¢er=0&layout=radial&nooverlap=&pure=0&zoom=1&ranksep=2.5&simple=0®en=1&font_size=12&group=0&id_networkmap=1"];} \ No newline at end of file diff --git a/dot/Ast.java b/dot/Ast.java deleted file mode 100644 index 7b020df..0000000 --- a/dot/Ast.java +++ /dev/null @@ -1,46 +0,0 @@ -import java.util.Map; -import java.util.LinkedList; -import java.util.Formatter; -import java.util.Locale; -import java.util.ArrayList; -class Ast implements AstNode { - private String name; - private Map attributes; - Ast(String name, Map attributes) { - this.name = name; - this.attributes = attributes; - } - public AstNode getAttribute(String name) { - return this.attributes.get(name); - } - public Map getAttributes() { - return this.attributes; - } - public String getName() { - return this.name; - } - public String toString() { - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - LinkedList attributes = new LinkedList(); - for (final Map.Entry attribute : this.attributes.entrySet()) { - final String name = attribute.getKey(); - final AstNode node = attribute.getValue(); - final String nodeStr = (node == null) ? "None" : node.toString(); - attributes.add(name + "=" + nodeStr); - } - formatter.format("(%s: %s)", this.name, Utility.join(attributes, ", ")); - return formatter.toString(); - } - public String toPrettyString() { - return toPrettyString(0); - } - public String toPrettyString(int indent) { - String spaces = Utility.getIndentString(indent); - ArrayList children = new ArrayList(); - for( Map.Entry attribute : this.attributes.entrySet() ) { - String valueString = attribute.getValue() == null ? "None" : attribute.getValue().toPrettyString(indent + 2).trim(); - children.add(spaces + " " + attribute.getKey() + "=" + valueString); - } - return spaces + "(" + this.name + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; - } -} diff --git a/dot/AstList.java b/dot/AstList.java deleted file mode 100644 index 220d2e1..0000000 --- a/dot/AstList.java +++ /dev/null @@ -1,20 +0,0 @@ -import java.util.ArrayList; -class AstList extends ArrayList implements AstNode { - public String toString() { - return "[" + Utility.join(this, ", ") + "]"; - } - public String toPrettyString() { - return toPrettyString(0); - } - public String toPrettyString(int indent) { - String spaces = Utility.getIndentString(indent); - if (this.size() == 0) { - return spaces + "[]"; - } - ArrayList elements = new ArrayList(); - for ( AstNode node : this ) { - elements.add(node.toPrettyString(indent + 2)); - } - return spaces + "[\n" + Utility.join(elements, ",\n") + "\n" + spaces + "]"; - } -} diff --git a/dot/AstNode.java b/dot/AstNode.java deleted file mode 100644 index 5e30462..0000000 --- a/dot/AstNode.java +++ /dev/null @@ -1,5 +0,0 @@ -interface AstNode { - public String toString(); - public String toPrettyString(); - public String toPrettyString(int indent); -} diff --git a/dot/AstTransform.java b/dot/AstTransform.java deleted file mode 100644 index f01ae0c..0000000 --- a/dot/AstTransform.java +++ /dev/null @@ -1 +0,0 @@ -interface AstTransform {} diff --git a/dot/AstTransformNodeCreator.java b/dot/AstTransformNodeCreator.java deleted file mode 100644 index f708c21..0000000 --- a/dot/AstTransformNodeCreator.java +++ /dev/null @@ -1,24 +0,0 @@ -import java.util.LinkedList; -import java.util.Map; -import java.util.LinkedHashMap; -class AstTransformNodeCreator implements AstTransform { - private String name; - private LinkedHashMap parameters; - AstTransformNodeCreator(String name, LinkedHashMap parameters) { - this.name = name; - this.parameters = parameters; - } - public Map getParameters() { - return this.parameters; - } - public String getName() { - return this.name; - } - public String toString() { - LinkedList items = new LinkedList(); - for (final Map.Entry entry : this.parameters.entrySet()) { - items.add(entry.getKey() + "=$" + entry.getValue().toString()); - } - return "AstNodeCreator: " + this.name + "( " + Utility.join(items, ", ") + " )"; - } -} diff --git a/dot/AstTransformSubstitution.java b/dot/AstTransformSubstitution.java deleted file mode 100644 index 404b7bd..0000000 --- a/dot/AstTransformSubstitution.java +++ /dev/null @@ -1,12 +0,0 @@ -class AstTransformSubstitution implements AstTransform { - private int index; - AstTransformSubstitution(int index) { - this.index = index; - } - public int getIndex() { - return this.index; - } - public String toString() { - return "AstSubstitution: $" + Integer.toString(this.index); - } -} diff --git a/dot/DotParser.java b/dot/DotParser.java deleted file mode 100644 index aece7de..0000000 --- a/dot/DotParser.java +++ /dev/null @@ -1,959 +0,0 @@ - -import java.util.*; -import java.util.HashMap; -import java.util.LinkedHashMap; -class DotParser implements Parser { - private TokenStream tokens; - private HashMap expressionParsers; - /* table[nonterminal][terminal] = rule */ - private static final int[][] table = { - { -1, -1, -1, 9, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 44 }, - { -1, -1, -1, 41, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, 6, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 35, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, 35, -1 }, - { -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, 22 }, - { 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 11, 11, 47, -1, -1, 32, -1, -1, 37, -1, -1, -1, -1, 11, 33, -1, 33 }, - { -1, -1, -1, -1, 13, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 51, -1, 51 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1 }, - { -1, -1, 15, 16, 16, 16, -1, -1, 16, -1, -1, 16, -1, -1, -1, -1, 16, 16, -1, 16 }, - { -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1 }, - { -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1 }, - { 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, -1, -1, 26, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, 23, -1, 19, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, 8 }, - { -1, -1, -1, -1, 3, -1, 3, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 4, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 4, -1 }, - { 14, 30, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, 30, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 39, -1, 40, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1 }, - }; - public enum TerminalId { - TERMINAL_COLON(0, "colon"), - TERMINAL_ARROW(1, "arrow"), - TERMINAL_RBRACE(2, "rbrace"), - TERMINAL_EDGE(3, "edge"), - TERMINAL_GRAPH(4, "graph"), - TERMINAL_EDGE_STMT_HINT(5, "edge_stmt_hint"), - TERMINAL_STRICT(6, "strict"), - TERMINAL_SEMI(7, "semi"), - TERMINAL_NODE_STMT_HINT(8, "node_stmt_hint"), - TERMINAL_DIGRAPH(9, "digraph"), - TERMINAL_COMMA(10, "comma"), - TERMINAL_VALUE_ASSIGN_HINT(11, "value_assign_hint"), - TERMINAL_RSQUARE(12, "rsquare"), - TERMINAL_LSQUARE(13, "lsquare"), - TERMINAL_ASSIGN(14, "assign"), - TERMINAL_IDENTIFIER(15, "identifier"), - TERMINAL_NODE(16, "node"), - TERMINAL_SUBGRAPH(17, "subgraph"), - TERMINAL_DASHDASH(18, "dashdash"), - TERMINAL_LBRACE(19, "lbrace"); - private final int id; - private final String string; - TerminalId(int id, String string) { - this.id = id; - this.string = string; - } - public int id() {return id;} - public String string() {return string;} - } - private class DotTerminalMap implements TerminalMap { - private Map id_to_str; - private Map str_to_id; - DotTerminalMap(TerminalId[] terminals) { - id_to_str = new HashMap(); - str_to_id = new HashMap(); - for( TerminalId terminal : terminals ) { - Integer id = new Integer(terminal.id()); - String str = terminal.string(); - id_to_str.put(id, str); - str_to_id.put(str, id); - } - } - public int get(String string) { return this.str_to_id.get(string); } - public String get(int id) { return this.id_to_str.get(id); } - public boolean isValid(String string) { return this.str_to_id.containsKey(string); } - public boolean isValid(int id) { return this.id_to_str.containsKey(id); } - } - DotParser() { - this.expressionParsers = new HashMap(); - } - public TerminalMap getTerminalMap() { - return new DotTerminalMap(TerminalId.values()); - } - public ParseTree parse(TokenStream tokens) throws SyntaxError { - this.tokens = tokens; - ParseTree tree = this.parse_graph(); - if (this.tokens.current() != null) { - throw new SyntaxError("Finished parsing without consuming all tokens."); - } - return tree; - } - private boolean isTerminal(TerminalId terminal) { - return (0 <= terminal.id() && terminal.id() <= 19); - } - private boolean isNonTerminal(TerminalId terminal) { - return (20 <= terminal.id() && terminal.id() <= 50); - } - private boolean isTerminal(int terminal) { - return (0 <= terminal && terminal <= 19); - } - private boolean isNonTerminal(int terminal) { - return (20 <= terminal && terminal <= 50); - } - private ParseTree parse_attr_type() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(20, "attr_type")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 9) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE.id()); - tree.add(next); - return tree; - } - else if (rule == 24) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE.id()); - tree.add(next); - return tree; - } - else if (rule == 25) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_attr_values() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(21, "attr_values")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 42) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 1); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("AttributeValue", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - subtree = this.parse__gen6(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_attr() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "attr")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 43) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE.id()); - tree.add(next); - subtree = this.parse__gen4(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen1() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen1")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 19) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 1) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - return tree; - } - private ParseTree parse_attr_stmt() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "attr_stmt")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 41) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("values", 1); - parameters.put("type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Attribute", parameters)); - subtree = this.parse_attr_type(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen5() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "_gen5")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 12) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA.id()); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_attr_values(); - tree.add( subtree); - subtree = this.parse__gen5(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_node_stmt() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "node_stmt")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 48) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 2); - parameters.put("id", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Node", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_NODE_STMT_HINT.id()); - tree.add(next); - subtree = this.parse_node_id(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen8() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "_gen8")); - tree.setList("mlist"); - if ( current != null ) { - if (current.getId() == 13 || current.getId() == 7) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 35) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_rhs(); - tree.add( subtree); - subtree = this.parse__gen8(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_edge_op() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "edge_op")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 18) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DASHDASH.id()); - tree.add(next); - return tree; - } - else if (rule == 28) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_ARROW.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen11() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "_gen11")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 19) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 17) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph_name(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_port_compass_pt() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "port_compass_pt")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 21) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_stmt() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "stmt")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 11) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_stmt(); - tree.add( subtree); - return tree; - } - else if (rule == 32) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_node_stmt(); - tree.add( subtree); - return tree; - } - else if (rule == 33) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph(); - tree.add( subtree); - return tree; - } - else if (rule == 37) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 3); - parameters.put("key", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Assign", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_VALUE_ASSIGN_HINT.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - else if (rule == 47) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_stmt(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_graph_type() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "graph_type")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 10) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_DIGRAPH.id()); - tree.add(next); - return tree; - } - else if (rule == 13) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_GRAPH.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_node_or_subgraph() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "node_or_subgraph")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_node_id(); - tree.add( subtree); - return tree; - } - else if (rule == 51) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_subgraph(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_node_id() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "node_id")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 38) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("port", 1); - tree.setAstTransformation(new AstTransformNodeCreator("NodeId", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - subtree = this.parse__gen9(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_attr_value_assign() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "attr_value_assign")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 5) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen2() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "_gen2")); - tree.setList("tlist"); - if ( current != null ) { - if (current.getId() == 2) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 16) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_stmt(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_edge_rhs() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "edge_rhs")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 45) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("edge_type", 0); - tree.setAstTransformation(new AstTransformNodeCreator("EdgeDeclaration", parameters)); - subtree = this.parse_edge_op(); - tree.add( subtree); - subtree = this.parse_node_or_subgraph(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen7() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "_gen7")); - tree.setList("mlist"); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 20) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_edge_rhs(); - tree.add( subtree); - subtree = this.parse__gen8(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_port_sub() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "port_sub")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 46) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - return tree; - } - else if (rule == 49) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("compass_point", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Port", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER.id()); - tree.add(next); - subtree = this.parse__gen10(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen4() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen4")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 12) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 26) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_values(); - tree.add( subtree); - subtree = this.parse__gen5(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen6() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "_gen6")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 10 || current.getId() == 12) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 19) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr_value_assign(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_subgraph() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "subgraph")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 8) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("statements", 2); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("SubGraph", parameters)); - subtree = this.parse__gen11(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_graph() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "graph")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 3) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("strict", 0); - parameters.put("type", 1); - parameters.put("name", 2); - parameters.put("statements", 4); - tree.setAstTransformation(new AstTransformNodeCreator("Graph", parameters)); - subtree = this.parse__gen0(); - tree.add( subtree); - subtree = this.parse_graph_type(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE.id()); - tree.add(next); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE.id()); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI.id()); - tree.add(next); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_port() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "port")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 31) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_COLON.id()); - tree.add(next); - subtree = this.parse_port_sub(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse__gen10() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "_gen10")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 7 || current.getId() == 18 || current.getId() == 13 || current.getId() == 1) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 0) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_port_compass_pt(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen9() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "_gen9")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 18 || current.getId() == 13 || current.getId() == 7 || current.getId() == 1) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 14) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_port(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen3() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "_gen3")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 7) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 34) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_attr(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen0() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "_gen0")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 9 || current.getId() == 4) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 40) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRICT.id()); - tree.add(next); - return tree; - } - return tree; - } - private ParseTree parse_edge_stmt() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "edge_stmt")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 7) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("node", 1); - parameters.put("attributes", 3); - parameters.put("edges", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Edge", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_EDGE_STMT_HINT.id()); - tree.add(next); - subtree = this.parse_node_or_subgraph(); - tree.add( subtree); - subtree = this.parse__gen7(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } - private ParseTree parse_subgraph_name() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[30][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "subgraph_name")); - tree.setList(null); - if (current == null) { - throw new SyntaxError("Error: unexpected end of file"); - } - if (rule == 29) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_SUBGRAPH.id()); - tree.add(next); - subtree = this.parse__gen1(); - tree.add( subtree); - return tree; - } - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Error: Unexpected symbol (%s) when parsing %s", current, stack[0].getMethodName()); - throw new SyntaxError(formatter.toString()); - } -} diff --git a/dot/ExpressionParser.java b/dot/ExpressionParser.java deleted file mode 100644 index 7dfbd91..0000000 --- a/dot/ExpressionParser.java +++ /dev/null @@ -1,3 +0,0 @@ -interface ExpressionParser extends Parser { - ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; -} diff --git a/dot/Lexer.java b/dot/Lexer.java deleted file mode 100644 index 0eb2c02..0000000 --- a/dot/Lexer.java +++ /dev/null @@ -1,416 +0,0 @@ -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.CharBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class SourceCode { - private File source; - private final String resource; - private String contents; - private int line; - private int col; - private int nchars; - - SourceCode(final String source, final String resource) { - this.contents = source; - this.resource = resource; - this.line = 1; - this.col = 1; - this.nchars = 0; - } - - SourceCode(final File source) throws IOException { - this(source, "utf-8", source.getCanonicalPath()); - } - - SourceCode(final File source, final String resource) throws IOException { - this(source, "utf-8", resource); - } - - SourceCode(final File source, final String encoding, final String resource) throws IOException, FileNotFoundException { - final FileChannel channel = new FileInputStream(source).getChannel(); - final MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); - final Charset cs = Charset.forName(encoding); - final CharsetDecoder cd = cs.newDecoder(); - final CharBuffer cb = cd.decode(buffer); - this.contents = cb.toString(); - this.resource = resource; - this.line = 1; - this.col = 1; - } - - public int getCharactersProcessed() { - return this.nchars; - } - - public void advance(final int amount) { - final String str = this.contents.substring(0, amount); - for ( final byte b : str.getBytes() ) { - if ( b == (byte) '\n' || b == (byte) '\r' ) { - this.line++; - this.col = 1; - } else { - this.col++; - } - } - this.contents = this.contents.substring(amount); - this.nchars += amount; - } - - public String getString() { - return this.contents; - } - - public String getResource() { - return this.resource; - } - - public int getLine() { - return this.line; - } - - public int getCol() { - return this.col; - } -} - -class LexerMatch { - private final List terminals; - LexerMatch() { this.terminals = null; } - LexerMatch(final List terminals) { this.terminals = terminals; } - public List getTerminals() { return this.terminals; } - public void add(final Terminal terminal) {this.terminals.add(terminal);} - public void addAll(final List terminals) {this.terminals.addAll(terminals);} - public void addAll(final LexerMatch match) {this.terminals.addAll(match.getTerminals());} -} - -abstract class TokenMatchCallback implements Callable { - protected Terminal terminal; - protected LexerState state; - protected void setContext(final Terminal terminal, final LexerState state) { - this.terminal = terminal; - this.state = state; - } - @Override - public abstract LexerMatch call(); -} - -class TokenLexer { - private final Pattern regex; - private final DotParser.TerminalId terminal; - private final TokenMatchCallback handler; - - TokenLexer(final Pattern regex, final DotParser.TerminalId terminal) { - this(regex, terminal, null); - } - - TokenLexer(final Pattern regex, final DotParser.TerminalId terminal, final TokenMatchCallback handler) { - this.regex = regex; - this.terminal = terminal; - this.handler = handler; - } - - LexerMatch match(final SourceCode source, final LexerState state) { - final Matcher m = this.regex.matcher(source.getString()); - - final String code = source.getString().length() > 20 ? source.getString().substring(0, 20) : source.getString(); - - if ( m.find() ) { - final String sourceString = m.group(); - Terminal terminal = null; - - if ( this.terminal != null ) { - terminal = new Terminal(this.terminal.id(), this.terminal.string(), Utility.base64_encode(sourceString.getBytes()), source.getResource(), source.getLine(), source.getCol()); - } - - source.advance(sourceString.length()); - - if ( this.handler != null ) { - this.handler.setContext(terminal, state); - return this.handler.call(); - } else { - final ArrayList list = new ArrayList(); - if ( terminal != null ) - list.add(terminal); - return new LexerMatch(list); - } - } - return null; - } -} - -class LexerState { - private ArrayList cache; - private int square_bracket; - LexerState() { - this.cache = new ArrayList(); - this.square_bracket = 0; - } - public void add(final Terminal terminal) { - this.cache.add(terminal); - } - public List getCache() { - return this.cache; - } - public void clearCache() { - this.cache = new ArrayList(); - } - public void square_inc() { - this.square_bracket++; - } - public void square_dec() { - this.square_bracket--; - } - public int square_level() { - return this.square_bracket; - } - - private boolean cache_contains(final DotParser.TerminalId input) { - if ( this.cache.size() > 0 ) { - for ( final Terminal t : this.cache ) { - if ( t.getId() == input.id() ) { - return true; - } - } - } - return false; - } - - private boolean cache_contains_edgeop() { - return cache_contains(DotParser.TerminalId.TERMINAL_DASHDASH) || cache_contains(DotParser.TerminalId.TERMINAL_ARROW); - } - - public LexerMatch stmt_end() { - final ArrayList tokens = new ArrayList(); - Terminal hint = null, semi = null; - - if ( this.cache.size() == 0 ) { - return null; - } - - if ( this.cache.size() >= 3 && - this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() && - this.cache.get(1).getId() == DotParser.TerminalId.TERMINAL_ASSIGN.id() && - this.cache.get(2).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { - final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_VALUE_ASSIGN_HINT; - hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); - } - else if ( cache_contains_edgeop() ) { - final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_EDGE_STMT_HINT; - hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); - } - else if ( this.cache.get(0).getId() == DotParser.TerminalId.TERMINAL_IDENTIFIER.id() ) { - final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_NODE_STMT_HINT; - hint = new Terminal( t.id(), t.string(), "", "Context-disambiguating token", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); - } - - if ( this.cache.get(this.cache.size()-1).getId() != DotParser.TerminalId.TERMINAL_SEMI.id() ) { - final DotParser.TerminalId t = DotParser.TerminalId.TERMINAL_SEMI; - semi = new Terminal( t.id(), t.string(), "", "Auto-inserted semi-colon", this.cache.get(0).getLine(), this.cache.get(0).getColumn()); - } - - if ( hint != null ) { - tokens.add(hint); - } - - tokens.addAll(this.cache); - - if ( semi != null ) { - tokens.add(semi); - } - - this.clearCache(); - return new LexerMatch(tokens); - } -} - -public class Lexer { - private static class BackslashNewlineCallback extends TokenMatchCallback { - /* called on \\[\r\n] */ - @Override - public LexerMatch call() { - return null; - } - } - private static class EofCallback extends TokenMatchCallback { - /* called on ^$ */ - @Override - public LexerMatch call() { - if ( this.state.getCache().size() > 0 ) { - final LexerMatch match = this.state.stmt_end(); - return match; - } else { - this.state.add(this.terminal); - //LexerMatch match = new LexerMatch(this.state.getCache()); - //this.state.clearCache(); - return null; - } - } - } - private static class RightBraceCallback extends TokenMatchCallback { - /* called on }[\r\n]* */ - @Override - public LexerMatch call() { - LexerMatch match = null; - if ( this.state.getCache().size() > 0 ) { - match = this.state.stmt_end(); - } else { - //match = new LexerMatch - this.state.add(this.terminal); - //LexerMatch match = new LexerMatch(this.state.getCache()); - //this.state.clearCache(); - } - return null; - } - } - private static class LeftBraceCallback extends TokenMatchCallback { - /* called on {[\r\n]* */ - @Override - public LexerMatch call() { - if ( this.state.getCache().size() > 0 ) { - this.state.add(this.terminal); - final LexerMatch match = new LexerMatch(this.state.getCache()); - this.state.clearCache(); - return match; - } - // output tokens in cache and clear cache. - return null; - } - } - private static class NewLineCallback extends TokenMatchCallback { - /* called on [\r\n]+ */ - @Override - public LexerMatch call() { - if ( this.state.square_level() == 0 ) { - return this.state.stmt_end(); - } - // if not within square brackets, goto stmt_end. - return null; - } - } - private static class LeftSquareBracketCallback extends TokenMatchCallback { - /* called on \\[ */ - @Override - public LexerMatch call() { - if ( this.terminal != null ) { - this.state.square_inc(); - this.state.add(this.terminal); - } - return null; - } - } - private static class RightSquareBracketCallback extends TokenMatchCallback { - /* called on \\] */ - @Override - public LexerMatch call() { - if ( this.terminal != null ) { - this.state.square_dec(); - this.state.add(this.terminal); - } - return null; - } - } - private static class TokenCallback extends TokenMatchCallback { - /* Called on all other tokens */ - @Override - public LexerMatch call() { - if ( this.terminal != null ) { - this.state.add(this.terminal); - } - return null; - } - } - - private ArrayList regex; - - public Lexer() { - this.regex = new ArrayList(); - this.regex.add( new TokenLexer(Pattern.compile("^$"), null, new EofCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^digraph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_DIGRAPH, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^graph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_GRAPH, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^subgraph(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_SUBGRAPH, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^strict(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_STRICT, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^edge(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_EDGE, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^node(?=[^a-zA-Z_])"), DotParser.TerminalId.TERMINAL_NODE, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^;"), DotParser.TerminalId.TERMINAL_SEMI, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\}"), DotParser.TerminalId.TERMINAL_RBRACE, new RightBraceCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\{[\r\n]*"), DotParser.TerminalId.TERMINAL_LBRACE, new LeftBraceCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\["), DotParser.TerminalId.TERMINAL_LSQUARE, new LeftSquareBracketCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\]"), DotParser.TerminalId.TERMINAL_RSQUARE, new RightSquareBracketCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\u002d\u002d"), DotParser.TerminalId.TERMINAL_DASHDASH, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\u002d\u003e"), DotParser.TerminalId.TERMINAL_ARROW, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^,"), DotParser.TerminalId.TERMINAL_COMMA, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^:"), DotParser.TerminalId.TERMINAL_COLON, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^="), DotParser.TerminalId.TERMINAL_ASSIGN, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\\\[\r\n]"), DotParser.TerminalId.TERMINAL_ASSIGN, new BackslashNewlineCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z\u0200-\u0377_]([0-9a-zA-Z\u0200-\u0377_])*|\"(\\\"|[^\"])*?\"|[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?))"), DotParser.TerminalId.TERMINAL_IDENTIFIER, new TokenCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^[\r\n]+"), null, new NewLineCallback()) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null, new TokenCallback()) ); - } - - private LexerMatch onMatch(Terminal terminal) { - return null; - } - - public List getTokens(SourceCode code) { - final LexerState state = new LexerState(); - final List terminals = new ArrayList(); - int consumed; - boolean progress = true; - - while (progress) { - progress = false; - consumed = code.getCharactersProcessed(); - for ( final TokenLexer lexer : regex ) { - final LexerMatch match = lexer.match(code, state); - - if (match != null) { - terminals.addAll(match.getTerminals()); - } - - if ( consumed < code.getCharactersProcessed() ) { - progress = true; - break; - } - } - } - return terminals; - } - - public static void main(final String[] args) { - if ( args.length < 1 ) { - System.err.println("Usage: Lexer "); - System.exit(-1); - } - - - try { - Lexer lexer = new Lexer(); - final SourceCode code = new SourceCode(new File(args[0])); - final ArrayList strs = new ArrayList(); - final List terminals = lexer.getTokens(code); - - for (final Terminal t : terminals) { - strs.add(" " + t.toString()); - } - - System.out.println("["); - System.out.println( Utility.join(strs, ",\n") ); - System.out.println("]"); - System.out.flush(); - } catch (final IOException e) { - System.err.println(e); - System.exit(-1); - } - } -} diff --git a/dot/NonTerminal.java b/dot/NonTerminal.java deleted file mode 100644 index b0b17e2..0000000 --- a/dot/NonTerminal.java +++ /dev/null @@ -1,17 +0,0 @@ -class NonTerminal { - private int id; - private String string; - NonTerminal(int id, String string) { - this.id = id; - this.string = string; - } - public int getId() { - return this.id; - } - public String getString() { - return this.string; - } - public String toString() { - return this.string; - } -} diff --git a/dot/ParseTree.java b/dot/ParseTree.java deleted file mode 100644 index b7a7bda..0000000 --- a/dot/ParseTree.java +++ /dev/null @@ -1,159 +0,0 @@ -import java.util.ArrayList; -import java.util.Map; -import java.util.List; -import java.util.LinkedHashMap; -class ParseTree implements ParseTreeNode { - private NonTerminal nonterminal; - private ArrayList children; - private boolean isExpr, isNud, isPrefix, isInfix, isExprNud; - private int nudMorphemeCount; - private Terminal listSeparator; - private String list; - private AstTransform astTransform; - ParseTree(NonTerminal nonterminal) { - this.nonterminal = nonterminal; - this.children = new ArrayList(); - this.astTransform = null; - this.isExpr = false; - this.isNud = false; - this.isPrefix = false; - this.isInfix = false; - this.isExprNud = false; - this.nudMorphemeCount = 0; - this.listSeparator = null; - this.list = ""; - } - public void setExpr(boolean value) { this.isExpr = value; } - public void setNud(boolean value) { this.isNud = value; } - public void setPrefix(boolean value) { this.isPrefix = value; } - public void setInfix(boolean value) { this.isInfix = value; } - public void setExprNud(boolean value) { this.isExprNud = value; } - public void setAstTransformation(AstTransform value) { this.astTransform = value; } - public void setNudMorphemeCount(int value) { this.nudMorphemeCount = value; } - public void setList(String value) { this.list = value; } - public void setListSeparator(Terminal value) { this.listSeparator = value; } - public int getNudMorphemeCount() { return this.nudMorphemeCount; } - public List getChildren() { return this.children; } - public boolean isInfix() { return this.isInfix; } - public boolean isPrefix() { return this.isPrefix; } - public boolean isExpr() { return this.isExpr; } - public boolean isNud() { return this.isNud; } - public boolean isExprNud() { return this.isExprNud; } - public void add(ParseTreeNode tree) { - if (this.children == null) { - this.children = new ArrayList(); - } - this.children.add(tree); - } - private boolean isCompoundNud() { - if ( this.children.size() > 0 && this.children.get(0) instanceof ParseTree ) { - ParseTree child = (ParseTree) this.children.get(0); - if ( child.isNud() && !child.isPrefix() && !this.isExprNud() && !this.isInfix() ) { - return true; - } - } - return false; - } - public AstNode toAst() { - if ( this.list == "slist" || this.list == "nlist" ) { - int offset = (this.children.size() > 0 && this.children.get(0) == this.listSeparator) ? 1 : 0; - AstList astList = new AstList(); - if ( this.children.size() == 0 ) { - return astList; - } - astList.add(this.children.get(offset).toAst()); - astList.addAll((AstList) this.children.get(offset + 1).toAst()); - return astList; - } else if ( this.list == "tlist" ) { - AstList astList = new AstList(); - if ( this.children.size() == 0 ) { - return astList; - } - astList.add(this.children.get(0).toAst()); - astList.addAll((AstList) this.children.get(2).toAst()); - return astList; - } else if ( this.list == "mlist" ) { - AstList astList = new AstList(); - int lastElement = this.children.size() - 1; - if ( this.children.size() == 0 ) { - return astList; - } - for (int i = 0; i < lastElement; i++) { - astList.add(this.children.get(i).toAst()); - } - astList.addAll((AstList) this.children.get(this.children.size() - 1).toAst()); - return astList; - } else if ( this.isExpr ) { - if ( this.astTransform instanceof AstTransformSubstitution ) { - AstTransformSubstitution astSubstitution = (AstTransformSubstitution) astTransform; - return this.children.get(astSubstitution.getIndex()).toAst(); - } else if ( this.astTransform instanceof AstTransformNodeCreator ) { - AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) this.astTransform; - LinkedHashMap parameters = new LinkedHashMap(); - ParseTreeNode child; - for ( final Map.Entry parameter : astNodeCreator.getParameters().entrySet() ) { - String name = parameter.getKey(); - int index = parameter.getValue().intValue(); - if ( index == '$' ) { - child = this.children.get(0); - } else if ( this.isCompoundNud() ) { - ParseTree firstChild = (ParseTree) this.children.get(0); - if ( index < firstChild.getNudMorphemeCount() ) { - child = firstChild.getChildren().get(index); - } else { - index = index - firstChild.getNudMorphemeCount() + 1; - child = this.children.get(index); - } - } else if ( this.children.size() == 1 && !(this.children.get(0) instanceof ParseTree) && !(this.children.get(0) instanceof List) ) { - // TODO: I don't think this should ever be called - child = this.children.get(0); - } else { - child = this.children.get(index); - } - parameters.put(name, child.toAst()); - } - return new Ast(astNodeCreator.getName(), parameters); - } - } else { - AstTransformSubstitution defaultAction = new AstTransformSubstitution(0); - AstTransform action = this.astTransform != null ? this.astTransform : defaultAction; - if (this.children.size() == 0) return null; - if (action instanceof AstTransformSubstitution) { - AstTransformSubstitution astSubstitution = (AstTransformSubstitution) action; - return this.children.get(astSubstitution.getIndex()).toAst(); - } else if (action instanceof AstTransformNodeCreator) { - AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) action; - LinkedHashMap evaluatedParameters = new LinkedHashMap(); - for ( Map.Entry baseParameter : astNodeCreator.getParameters().entrySet() ) { - String name = baseParameter.getKey(); - int index2 = baseParameter.getValue().intValue(); - evaluatedParameters.put(name, this.children.get(index2).toAst()); - } - return new Ast(astNodeCreator.getName(), evaluatedParameters); - } - } - return null; - } - public String toString() { - ArrayList children = new ArrayList(); - for (ParseTreeNode child : this.children) { - children.add(child.toString()); - } - return "(" + this.nonterminal.getString() + ": " + Utility.join(children, ", ") + ")"; - } - public String toPrettyString() { - return toPrettyString(0); - } - public String toPrettyString(int indent) { - if (this.children.size() == 0) { - return "(" + this.nonterminal.toString() + ": )"; - } - String spaces = Utility.getIndentString(indent); - ArrayList children = new ArrayList(); - for ( ParseTreeNode node : this.children ) { - String sub = node.toPrettyString(indent + 2).trim(); - children.add(spaces + " " + sub); - } - return spaces + "(" + this.nonterminal.toString() + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")"; - } -} diff --git a/dot/ParseTreeNode.java b/dot/ParseTreeNode.java deleted file mode 100644 index 9d6eb97..0000000 --- a/dot/ParseTreeNode.java +++ /dev/null @@ -1,6 +0,0 @@ -public interface ParseTreeNode { - public AstNode toAst(); - public String toString(); - public String toPrettyString(); - public String toPrettyString(int indent); -} diff --git a/dot/Parser.java b/dot/Parser.java deleted file mode 100644 index 8746412..0000000 --- a/dot/Parser.java +++ /dev/null @@ -1,4 +0,0 @@ -interface Parser { - ParseTree parse(TokenStream tokens) throws SyntaxError; - TerminalMap getTerminalMap(); -} diff --git a/dot/ParserMain.java b/dot/ParserMain.java deleted file mode 100644 index 3f3c231..0000000 --- a/dot/ParserMain.java +++ /dev/null @@ -1,50 +0,0 @@ -import org.json.*; -import java.io.*; -class ParserMain { - private static Parser getParser(String name) throws Exception { - if (name.equals("dot")) { - return new DotParser(); - } - throw new Exception("Invalid grammar name: " + name); - } - public static void main(String args[]) { - final String grammars = "dot"; - if ( args.length < 2 ) { - System.out.println("Usage: ParserMain <" + grammars + "> "); - System.exit(-1); - } - final String grammar = args[0].toLowerCase(); - try { - Parser parser = getParser(grammar); - TerminalMap terminals = parser.getTerminalMap(); - TokenStream tokens = new TokenStream(terminals); - String contents = Utility.readStdin(); - JSONArray arr = new JSONArray(contents); - for ( int i = 0; i < arr.length(); i++ ) { - JSONObject token = arr.getJSONObject(i); - tokens.add(new Terminal( - terminals.get(token.getString("terminal")), - token.getString("terminal"), - token.getString("source_string"), - token.getString("resource"), - token.getInt("line"), - token.getInt("col") - )); - } - ParseTreeNode parsetree = parser.parse(tokens); - if ( args.length > 1 && args[1].equals("ast") ) { - AstNode ast = parsetree.toAst(); - if ( ast != null ) { - System.out.println(ast.toPrettyString()); - } else { - System.out.println("None"); - } - } else { - System.out.println(parsetree.toPrettyString()); - } - } catch (Exception e) { - System.err.println(e.getMessage()); - System.exit(-1); - } - } -} diff --git a/dot/SyntaxError.java b/dot/SyntaxError.java deleted file mode 100644 index 9ea950e..0000000 --- a/dot/SyntaxError.java +++ /dev/null @@ -1,5 +0,0 @@ -class SyntaxError extends Exception { - SyntaxError(String message) { - super(message); - } -} diff --git a/dot/TODO b/dot/TODO deleted file mode 100644 index 39e3d43..0000000 --- a/dot/TODO +++ /dev/null @@ -1,40 +0,0 @@ -Lexer ------ - -1) There are 3 hint tokens that need to be emitted properly: - 0) value_assign_hint - comes before any sequence that looks like: identifier + assign + identifier - 1) edge_stmt_hint - a statement that contains an edge_op - 2) node_stmt_hint - statement that does NOT contain edge_op and starts with: node_id - -2) Lexer Notes: - 0) 'identifier' is: - a) Any string of alphabetic ([a-zA-Z\200-\377]) characters, underscores ('_') or digits ([0-9]), not beginning with a digit - i) [a-zA-Z\\200-\\377_]([0-9a-zA-Z\\200-\\377_])* - b) a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? ) - i) [-]?(\\.[0-9]+|[0-9]+(.[0-9]*)?) - c) any double-quoted string ("...") possibly containing escaped quotes (\") - i) \"(\\\"|[^\"])*\" - d) an HTML string (<...>) - i) <[^>]+> - -3) Algorithm: - 0) Cache starts out empty - 1) Collect tokens in a cache until one of the following conditions happens: - a) [\n\r]+ - i) if not within square brackets, goto stmt_end. - b) {[\r\n]* - i) output tokens in cache and clear cache. - c) }[\r\n]+, or EOF - i) if there are tokens in the cache, goto stmt_end. - d) \\[\r\n] - i) return - stmt_end) - i) if cache = ['identifier' + 'assign' + 'identifier'], hint = value_assign_hint - ii) if cache contains edgeop, hint = edge_stmt_hint - iii) if cache[0] = 'identifier' and cache does not contain edgeop, hint = node_stmt_hint - iv) if cache[-1] != 'semi', semi = 'semi' - end) - i) rval = [hint] + cache + [semi] - ii) cache = list() - iii) return rval - diff --git a/dot/Terminal.java b/dot/Terminal.java deleted file mode 100644 index acc252b..0000000 --- a/dot/Terminal.java +++ /dev/null @@ -1,51 +0,0 @@ -import java.util.Formatter; -import java.util.Locale; -class Terminal implements AstNode, ParseTreeNode -{ - private int id; - private String terminal_str; - private String base64_source_string; - private String resource; - private int line; - private int col; - Terminal(int id, String terminal_str, String base64_source_string, String resource, int line, int col) { - this.id = id; - this.terminal_str = terminal_str; - this.base64_source_string = base64_source_string; - this.resource = resource; - this.line = line; - this.col = col; - } - public int getId() { - return this.id; - } - public String getTerminalStr() { - return this.terminal_str; - } - public String getBase64SourceString() { - return this.base64_source_string; - } - public String getResource() { - return this.resource; - } - public int getLine() { - return this.line; - } - public int getColumn() { - return this.col; - } - public String toString() { - StringBuilder sb = new StringBuilder(); - Formatter formatter = new Formatter(sb, Locale.US); - formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), this.getBase64SourceString()); - return formatter.toString(); - } - public String toPrettyString() { - return toPrettyString(0); - } - public String toPrettyString(int indent) { - String spaces = Utility.getIndentString(indent); - return spaces + this.toString(); - } - public AstNode toAst() { return this; } -} diff --git a/dot/TerminalMap.java b/dot/TerminalMap.java deleted file mode 100644 index f198d39..0000000 --- a/dot/TerminalMap.java +++ /dev/null @@ -1,6 +0,0 @@ -interface TerminalMap { - int get(String string); - String get(int id); - boolean isValid(String string); - boolean isValid(int id); -} diff --git a/dot/TokenStream.java b/dot/TokenStream.java deleted file mode 100644 index b50e557..0000000 --- a/dot/TokenStream.java +++ /dev/null @@ -1,44 +0,0 @@ -import java.util.ArrayList; -import java.util.Formatter; -import java.util.Locale; -class TokenStream extends ArrayList { - private int index; - private TerminalMap terminals; - TokenStream(TerminalMap terminals) { - this.terminals = terminals; - reset(); - } - public void reset() { - this.index = 0; - } - public Terminal advance() { - this.index += 1; - return this.current(); - } - public Terminal current() { - try { - return this.get(this.index); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - public Terminal expect(int expecting) throws SyntaxError { - Terminal current = current(); - if (current == null) { - throw new SyntaxError( "No more tokens. Expecting " + this.terminals.get(expecting) ); - } - if (current.getId() != expecting) { - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - formatter.format("Unexpected symbol when parsing %s. Expected %s, got %s.", stack[2].getMethodName(), this.terminals.get(expecting), current != null ? current.getTerminalStr() : ""); - throw new SyntaxError(formatter.toString()); - } - Terminal next = advance(); - if ( next != null && !this.terminals.isValid(next.getId()) ) { - Formatter formatter = new Formatter(new StringBuilder(), Locale.US); - formatter.format("Invalid symbol ID: %d (%s)", next.getId(), next.getTerminalStr()); - throw new SyntaxError(formatter.toString()); - } - return current; - } -} diff --git a/dot/Utility.java b/dot/Utility.java deleted file mode 100644 index 60bbde1..0000000 --- a/dot/Utility.java +++ /dev/null @@ -1,81 +0,0 @@ -import java.util.Collection; -import java.util.Iterator; -import java.io.IOException; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.nio.*; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -class Utility { - public static String join(Collection s, String delimiter) { - StringBuilder builder = new StringBuilder(); - Iterator iter = s.iterator(); - while (iter.hasNext()) { - builder.append(iter.next()); - if (!iter.hasNext()) { - break; - } - builder.append(delimiter); - } - return builder.toString(); - } - public static String getIndentString(int spaces) { - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < spaces; i++) { - sb.append(' '); - } - return sb.toString(); - } - public static String base64_encode(byte[] bytes) { - int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4; - int cycle = 0, b64_index = 0; - byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); - byte[] b64 = new byte[b64_len]; - byte[] buffer = new byte[3]; - Arrays.fill(buffer, (byte) -1); - for (byte b : bytes) { - int index = cycle % 3; - buffer[index] = b; - boolean last = (cycle == (bytes.length - 1)); - if ( index == 2 || last ) { - if ( last ) { - if ( buffer[1] == -1 ) buffer[1] = 0; - if ( buffer[2] == -1 ) buffer[2] = 0; - } - b64[b64_index++] = alphabet[buffer[0] >> 2]; - b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)]; - b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)]; - b64[b64_index++] = alphabet[buffer[2] & 0x3f]; - if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '='; - if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '='; - Arrays.fill(buffer, (byte) -1); - } - cycle++; - } - return new String(b64); - } - public static String readStdin() throws IOException { - InputStreamReader stream = new InputStreamReader(System.in, "utf-8"); - char buffer[] = new char[System.in.available()]; - try { - stream.read(buffer, 0, System.in.available()); - } finally { - stream.close(); - } - return new String(buffer); - } - public static String readFile(String path) throws IOException { - FileInputStream stream = new FileInputStream(new File(path)); - try { - FileChannel fc = stream.getChannel(); - MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); - /* Instead of using default, pass in a decoder. */ - return Charset.defaultCharset().decode(bb).toString(); - } - finally { - stream.close(); - } - } -} diff --git a/dot/dot.zgr b/dot/dot.zgr deleted file mode 100644 index 6ff6a9a..0000000 --- a/dot/dot.zgr +++ /dev/null @@ -1,28 +0,0 @@ -{ - "ll1": { - "start": "graph", - "rules": [ - "graph := optional('strict') + graph_type + optional('identifier') + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' + 'semi' -> Graph(strict=$0, type=$1, name=$2, statements=$4)", - "graph_type := 'graph' | 'digraph'", - "stmt := node_stmt | edge_stmt | attr_stmt | subgraph", - "stmt := 'value_assign_hint' + 'identifier' + 'assign' + 'identifier' -> Assign(key=$1, value=$3)", - "attr_stmt := attr_type + list(attr) -> Attribute(type=$0, values=$1)", - "attr_type := 'graph' | 'node' | 'edge'", - "attr := 'lsquare' + list(attr_values, 'comma') + 'rsquare' -> $1", - "attr_values := 'identifier' + optional(attr_value_assign) -> AttributeValue(key=$0, value=$1)", - "attr_value_assign := 'assign' + 'identifier' -> $1", - "edge_stmt := 'edge_stmt_hint' + node_or_subgraph + mlist(edge_rhs, 1) + list(attr) -> Edge(node=$1, edges=$2, attributes=$3)", - "edge_rhs := edge_op + node_or_subgraph -> EdgeDeclaration( edge_type=$0, node=$1 )", - "node_or_subgraph := node_id | subgraph", - "edge_op := 'arrow' | 'dashdash'", - "node_stmt := 'node_stmt_hint' + node_id + list(attr) -> Node(id=$1, attributes=$2)", - "node_id := 'identifier' + optional(port) -> NodeId(name=$0, port=$1)", - "port := 'colon' + port_sub -> $1", - "port_sub := 'identifier' + optional(port_compass_pt) -> Port(name=$0, compass_point=$1)", - "port_compass_pt := 'colon' + 'identifier' -> $1", - "port_sub := 'colon' + 'identifier' -> Port(name=$1)", - "subgraph := optional(subgraph_name) + 'lbrace' + tlist(stmt, 'semi') + 'rbrace' -> SubGraph(name=$0, statements=$2)", - "subgraph_name := 'subgraph' + optional('identifier') - > $1" - ] - } -} diff --git a/dot/org/json/CDL.java b/dot/org/json/CDL.java deleted file mode 100755 index fd5d476..0000000 --- a/dot/org/json/CDL.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * This provides static methods to convert comma delimited text into a - * JSONArray, and to covert a JSONArray into comma delimited text. Comma - * delimited text is a very popular format for data interchange. It is - * understood by most database, spreadsheet, and organizer programs. - *

    - * Each row of text represents a row in a table or a data record. Each row - * ends with a NEWLINE character. Each row contains one or more values. - * Values are separated by commas. A value can contain any character except - * for comma, unless is is wrapped in single quotes or double quotes. - *

    - * The first row usually contains the names of the columns. - *

    - * A comma delimited list can be converted into a JSONArray of JSONObjects. - * The names for the elements in the JSONObjects can be taken from the names - * in the first row. - * @author JSON.org - * @version 2010-12-24 - */ -public class CDL { - - /** - * Get the next value. The value can be wrapped in quotes. The value can - * be empty. - * @param x A JSONTokener of the source text. - * @return The value string, or null if empty. - * @throws JSONException if the quoted string is badly formed. - */ - private static String getValue(JSONTokener x) throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = x.next(); - } while (c == ' ' || c == '\t'); - switch (c) { - case 0: - return null; - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = x.next(); - if (c == q) { - break; - } - if (c == 0 || c == '\n' || c == '\r') { - throw x.syntaxError("Missing close quote '" + q + "'."); - } - sb.append(c); - } - return sb.toString(); - case ',': - x.back(); - return ""; - default: - x.back(); - return x.nextTo(','); - } - } - - /** - * Produce a JSONArray of strings from a row of comma delimited values. - * @param x A JSONTokener of the source text. - * @return A JSONArray of strings. - * @throws JSONException - */ - public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { - JSONArray ja = new JSONArray(); - for (;;) { - String value = getValue(x); - char c = x.next(); - if (value == null || - (ja.length() == 0 && value.length() == 0 && c != ',')) { - return null; - } - ja.put(value); - for (;;) { - if (c == ',') { - break; - } - if (c != ' ') { - if (c == '\n' || c == '\r' || c == 0) { - return ja; - } - throw x.syntaxError("Bad character '" + c + "' (" + - (int)c + ")."); - } - c = x.next(); - } - } - } - - /** - * Produce a JSONObject from a row of comma delimited text, using a - * parallel JSONArray of strings to provides the names of the elements. - * @param names A JSONArray of names. This is commonly obtained from the - * first row of a comma delimited text file using the rowToJSONArray - * method. - * @param x A JSONTokener of the source text. - * @return A JSONObject combining the names and values. - * @throws JSONException - */ - public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) - throws JSONException { - JSONArray ja = rowToJSONArray(x); - return ja != null ? ja.toJSONObject(names) : null; - } - - /** - * Produce a comma delimited text row from a JSONArray. Values containing - * the comma character will be quoted. Troublesome characters may be - * removed. - * @param ja A JSONArray of strings. - * @return A string ending in NEWLINE. - */ - public static String rowToString(JSONArray ja) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - if (i > 0) { - sb.append(','); - } - Object object = ja.opt(i); - if (object != null) { - String string = object.toString(); - if (string.length() > 0 && (string.indexOf(',') >= 0 || - string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 || - string.indexOf(0) >= 0 || string.charAt(0) == '"')) { - sb.append('"'); - int length = string.length(); - for (int j = 0; j < length; j += 1) { - char c = string.charAt(j); - if (c >= ' ' && c != '"') { - sb.append(c); - } - } - sb.append('"'); - } else { - sb.append(string); - } - } - } - sb.append('\n'); - return sb.toString(); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string, - * using the first row as a source of names. - * @param x The JSONTokener containing the comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONTokener x) throws JSONException { - return toJSONArray(rowToJSONArray(x), x); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param string The comma delimited text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, String string) - throws JSONException { - return toJSONArray(names, new JSONTokener(string)); - } - - /** - * Produce a JSONArray of JSONObjects from a comma delimited text string - * using a supplied JSONArray as the source of element names. - * @param names A JSONArray of strings. - * @param x A JSONTokener of the source text. - * @return A JSONArray of JSONObjects. - * @throws JSONException - */ - public static JSONArray toJSONArray(JSONArray names, JSONTokener x) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (;;) { - JSONObject jo = rowToJSONObject(names, x); - if (jo == null) { - break; - } - ja.put(jo); - } - if (ja.length() == 0) { - return null; - } - return ja; - } - - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects. The - * first row will be a list of names obtained by inspecting the first - * JSONObject. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - JSONObject jo = ja.optJSONObject(0); - if (jo != null) { - JSONArray names = jo.names(); - if (names != null) { - return rowToString(names) + toString(names, ja); - } - } - return null; - } - - /** - * Produce a comma delimited text from a JSONArray of JSONObjects using - * a provided list of names. The list of names is not included in the - * output. - * @param names A JSONArray of strings. - * @param ja A JSONArray of JSONObjects. - * @return A comma delimited text. - * @throws JSONException - */ - public static String toString(JSONArray names, JSONArray ja) - throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < ja.length(); i += 1) { - JSONObject jo = ja.optJSONObject(i); - if (jo != null) { - sb.append(rowToString(jo.toJSONArray(names))); - } - } - return sb.toString(); - } -} diff --git a/dot/org/json/Cookie.java b/dot/org/json/Cookie.java deleted file mode 100755 index 9cf5ce2..0000000 --- a/dot/org/json/Cookie.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * Convert a web browser cookie specification to a JSONObject and back. - * JSON and Cookies are both notations for name/value pairs. - * @author JSON.org - * @version 2010-12-24 - */ -public class Cookie { - - /** - * Produce a copy of a string in which the characters '+', '%', '=', ';' - * and control characters are replaced with "%hh". This is a gentle form - * of URL encoding, attempting to cause as little distortion to the - * string as possible. The characters '=' and ';' are meta characters in - * cookies. By convention, they are escaped using the URL-encoding. This is - * only a convention, not a standard. Often, cookies are expected to have - * encoded values. We encode '=' and ';' because we must. We encode '%' and - * '+' because they are meta characters in URL encoding. - * @param string The source string. - * @return The escaped result. - */ - public static String escape(String string) { - char c; - String s = string.trim(); - StringBuffer sb = new StringBuffer(); - int length = s.length(); - for (int i = 0; i < length; i += 1) { - c = s.charAt(i); - if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') { - sb.append('%'); - sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16)); - sb.append(Character.forDigit((char)(c & 0x0f), 16)); - } else { - sb.append(c); - } - } - return sb.toString(); - } - - - /** - * Convert a cookie specification string into a JSONObject. The string - * will contain a name value pair separated by '='. The name and the value - * will be unescaped, possibly converting '+' and '%' sequences. The - * cookie properties may follow, separated by ';', also represented as - * name=value (except the secure property, which does not have a value). - * The name will be stored under the key "name", and the value will be - * stored under the key "value". This method does not do checking or - * validation of the parameters. It only converts the cookie string into - * a JSONObject. - * @param string The cookie specification string. - * @return A JSONObject containing "name", "value", and possibly other - * members. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - String name; - JSONObject jo = new JSONObject(); - Object value; - JSONTokener x = new JSONTokener(string); - jo.put("name", x.nextTo('=')); - x.next('='); - jo.put("value", x.nextTo(';')); - x.next(); - while (x.more()) { - name = unescape(x.nextTo("=;")); - if (x.next() != '=') { - if (name.equals("secure")) { - value = Boolean.TRUE; - } else { - throw x.syntaxError("Missing '=' in cookie parameter."); - } - } else { - value = unescape(x.nextTo(';')); - x.next(); - } - jo.put(name, value); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie specification string. The JSONObject - * must contain "name" and "value" members. - * If the JSONObject contains "expires", "domain", "path", or "secure" - * members, they will be appended to the cookie specification string. - * All other members are ignored. - * @param jo A JSONObject - * @return A cookie specification string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - - sb.append(escape(jo.getString("name"))); - sb.append("="); - sb.append(escape(jo.getString("value"))); - if (jo.has("expires")) { - sb.append(";expires="); - sb.append(jo.getString("expires")); - } - if (jo.has("domain")) { - sb.append(";domain="); - sb.append(escape(jo.getString("domain"))); - } - if (jo.has("path")) { - sb.append(";path="); - sb.append(escape(jo.getString("path"))); - } - if (jo.optBoolean("secure")) { - sb.append(";secure"); - } - return sb.toString(); - } - - /** - * Convert %hh sequences to single characters, and - * convert plus to space. - * @param string A string that may contain - * + (plus) and - * %hh sequences. - * @return The unescaped string. - */ - public static String unescape(String string) { - int length = string.length(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; ++i) { - char c = string.charAt(i); - if (c == '+') { - c = ' '; - } else if (c == '%' && i + 2 < length) { - int d = JSONTokener.dehexchar(string.charAt(i + 1)); - int e = JSONTokener.dehexchar(string.charAt(i + 2)); - if (d >= 0 && e >= 0) { - c = (char)(d * 16 + e); - i += 2; - } - } - sb.append(c); - } - return sb.toString(); - } -} diff --git a/dot/org/json/CookieList.java b/dot/org/json/CookieList.java deleted file mode 100755 index 7f4fe07..0000000 --- a/dot/org/json/CookieList.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert a web browser cookie list string to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class CookieList { - - /** - * Convert a cookie list into a JSONObject. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The names and the values - * will be unescaped, possibly converting '+' and '%' sequences. - * - * To add a cookie to a cooklist, - * cookielistJSONObject.put(cookieJSONObject.getString("name"), - * cookieJSONObject.getString("value")); - * @param string A cookie list string - * @return A JSONObject - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - JSONTokener x = new JSONTokener(string); - while (x.more()) { - String name = Cookie.unescape(x.nextTo('=')); - x.next('='); - jo.put(name, Cookie.unescape(x.nextTo(';'))); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into a cookie list. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The characters '%', '+', '=', and ';' - * in the names and values are replaced by "%hh". - * @param jo A JSONObject - * @return A cookie list string - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - boolean b = false; - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!jo.isNull(string)) { - if (b) { - sb.append(';'); - } - sb.append(Cookie.escape(string)); - sb.append("="); - sb.append(Cookie.escape(jo.getString(string))); - b = true; - } - } - return sb.toString(); - } -} diff --git a/dot/org/json/HTTP.java b/dot/org/json/HTTP.java deleted file mode 100755 index 43d04a8..0000000 --- a/dot/org/json/HTTP.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - -/** - * Convert an HTTP header to a JSONObject and back. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTP { - - /** Carriage return/line feed. */ - public static final String CRLF = "\r\n"; - - /** - * Convert an HTTP header string into a JSONObject. It can be a request - * header or a response header. A request header will contain - *

    {
    -     *    Method: "POST" (for example),
    -     *    "Request-URI": "/" (for example),
    -     *    "HTTP-Version": "HTTP/1.1" (for example)
    -     * }
    - * A response header will contain - *
    {
    -     *    "HTTP-Version": "HTTP/1.1" (for example),
    -     *    "Status-Code": "200" (for example),
    -     *    "Reason-Phrase": "OK" (for example)
    -     * }
    - * In addition, the other parameters in the header will be captured, using - * the HTTP field names as JSON names, so that
    -     *    Date: Sun, 26 May 2002 18:06:04 GMT
    -     *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
    -     *    Cache-Control: no-cache
    - * become - *
    {...
    -     *    Date: "Sun, 26 May 2002 18:06:04 GMT",
    -     *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
    -     *    "Cache-Control": "no-cache",
    -     * ...}
    - * It does no further checking or conversion. It does not parse dates. - * It does not do '%' transforms on URLs. - * @param string An HTTP header string. - * @return A JSONObject containing the elements and attributes - * of the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - HTTPTokener x = new HTTPTokener(string); - String token; - - token = x.nextToken(); - if (token.toUpperCase().startsWith("HTTP")) { - -// Response - - jo.put("HTTP-Version", token); - jo.put("Status-Code", x.nextToken()); - jo.put("Reason-Phrase", x.nextTo('\0')); - x.next(); - - } else { - -// Request - - jo.put("Method", token); - jo.put("Request-URI", x.nextToken()); - jo.put("HTTP-Version", x.nextToken()); - } - -// Fields - - while (x.more()) { - String name = x.nextTo(':'); - x.next(':'); - jo.put(name, x.nextTo('\0')); - x.next(); - } - return jo; - } - - - /** - * Convert a JSONObject into an HTTP header. A request header must contain - *
    {
    -     *    Method: "POST" (for example),
    -     *    "Request-URI": "/" (for example),
    -     *    "HTTP-Version": "HTTP/1.1" (for example)
    -     * }
    - * A response header must contain - *
    {
    -     *    "HTTP-Version": "HTTP/1.1" (for example),
    -     *    "Status-Code": "200" (for example),
    -     *    "Reason-Phrase": "OK" (for example)
    -     * }
    - * Any other members of the JSONObject will be output as HTTP fields. - * The result will end with two CRLF pairs. - * @param jo A JSONObject - * @return An HTTP header string. - * @throws JSONException if the object does not contain enough - * information. - */ - public static String toString(JSONObject jo) throws JSONException { - Iterator keys = jo.keys(); - String string; - StringBuffer sb = new StringBuffer(); - if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { - sb.append(jo.getString("HTTP-Version")); - sb.append(' '); - sb.append(jo.getString("Status-Code")); - sb.append(' '); - sb.append(jo.getString("Reason-Phrase")); - } else if (jo.has("Method") && jo.has("Request-URI")) { - sb.append(jo.getString("Method")); - sb.append(' '); - sb.append('"'); - sb.append(jo.getString("Request-URI")); - sb.append('"'); - sb.append(' '); - sb.append(jo.getString("HTTP-Version")); - } else { - throw new JSONException("Not enough material for an HTTP header."); - } - sb.append(CRLF); - while (keys.hasNext()) { - string = keys.next().toString(); - if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && - !"Reason-Phrase".equals(string) && !"Method".equals(string) && - !"Request-URI".equals(string) && !jo.isNull(string)) { - sb.append(string); - sb.append(": "); - sb.append(jo.getString(string)); - sb.append(CRLF); - } - } - sb.append(CRLF); - return sb.toString(); - } -} diff --git a/dot/org/json/HTTPTokener.java b/dot/org/json/HTTPTokener.java deleted file mode 100755 index f62b3d5..0000000 --- a/dot/org/json/HTTPTokener.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The HTTPTokener extends the JSONTokener to provide additional methods - * for the parsing of HTTP headers. - * @author JSON.org - * @version 2010-12-24 - */ -public class HTTPTokener extends JSONTokener { - - /** - * Construct an HTTPTokener from a string. - * @param string A source string. - */ - public HTTPTokener(String string) { - super(string); - } - - - /** - * Get the next token or string. This is used in parsing HTTP headers. - * @throws JSONException - * @return A String. - */ - public String nextToken() throws JSONException { - char c; - char q; - StringBuffer sb = new StringBuffer(); - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == '"' || c == '\'') { - q = c; - for (;;) { - c = next(); - if (c < ' ') { - throw syntaxError("Unterminated string."); - } - if (c == q) { - return sb.toString(); - } - sb.append(c); - } - } - for (;;) { - if (c == 0 || Character.isWhitespace(c)) { - return sb.toString(); - } - sb.append(c); - c = next(); - } - } -} diff --git a/dot/org/json/JSONArray.class b/dot/org/json/JSONArray.class deleted file mode 100644 index 83e6c9969cb05b848d6436f3b238b1765f0e822e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9162 zcmbVR33yc3b^hS@B*femBbLR6A#!VCdNtJx=Yg9ZL@SuT9U?To3?gp6KwTA_q`dt8I5SZ z@LBiGyURKM`OmrMp8Nd9hcCYZ;3gIGqX(Bwyyk}omy6JZZ~EC>_G1*j<-@n-`MNZJ zT!eY}6Pfjfy#A>Ve`ey(<>z0>g6|aLyZFmu{1x7m<}E*G|Fy{e8$bRQ-}B@9_<=M( zl*xZ*;_rR<2R|m*i~rHYKlw2UmwotWdHzV6AN%kx^88m>ais`9!B0irznS=%4{!TX zho4L5zx(hXKK!SNU-&T_|K-O9{I`k!@!=hLf7g%A_@#;e_2E4e@B467dVl3d8?O2A zfr$Rl#GoIG#N+WRv?@_IR+@3b9}zXF@iIDrM5tt0`)#Oq?dobW_bBw`!)TY88t29#|5OhYqwv5=n*1mffNILv#9) zk)Ao3?q-F;g^_3^d7FY!H*1T6cUi0}tWeq#iH2MI_I8Bhn?fBu>=|Fz5{q}w*`0_* z=d9hhzI9VhIwJg@t6Yi8195Yp&sb=M@T;H*q6Z9x8G`hoLS>2jhF5%7;>gVXvSga=; ziqbAlx?7=$eamBg+9K&%&WIrg>|GP3DCt_GVDVjS)I2GS6$M$w>j9Ei;!L!4DvTR8 zGlRzD)RtJZ+g7sHhGG*j%mjxY0*fSC`+9n~W_K(?D`w_n(Pg`{kb%v$J>h6~a+h{2 zZ8BoLG|`arwzU8x)b2a-kCG4;{VTX&866e*nk2_4kWS4Cr*Q}i- zCbB1OVr|`;;XvJf%V7T*!S?nM?AW@y^YShMrh*C$BgIaBXN|2}o>!bGT06qX47Umf zc=HJJ>fDZTd_KZd#z=m%6dKbU>0RpH4f!pisF6(K&`3ecp^?m;nFZiF_RdOA)cg7R z1{cP|dt>)Ag;>d$M36mOp*|<0*qbVcHAl39FBwaRQbk?9xKWc#Rj*L6FCIx!*;L0P zk=UFz>0zd_<8P=#VfwI1!kSJu3FWeOf1!@~=1F?9Zb{i96MOJolQnO&%FHM4})Kc@+t<0yE zTA-ROwNTBo)FO48rEXV?O|`^QOI5R}mRV}KT4CY0)JhA_;Iu+jmgG!ES6Dh^h#Vl1 zP*33gP)}btkk}RL>*)$~go!bs6TQIf%%paC3(2`O+rl5>Fn6CO&2=y=?Thquh2vyA zqhqV3R;ks}NP6BDh{lqEow2@X7loY11tP{_<^)TvRd-mbMKvju<%(r&>$r}~JcHmHqhS8LQRR?1z1qWbup zZK+N8jHNa!9+c%-Z0Zo9Q(bE^22=f*tjXzJQay>%)&!>*uv+~Z{eeO#KLhrZs8~%wQvF_E&MJ% zt^f;9RF?`{ z_$m%t_&t1reQKwm%j{Z(mDnNg*Di%-6dO`^nl4H`UG!wd$dP;`^$(d(H63+f|<(GJPrxciW0c@9G zEl!n`mk1`C+B^iM&j<}61F|sG+Z&FO(?<6ar>t?CWp_DQj^JygY8)~kcer5Xl9r7t zXt`^S6JA_g7{0HMS&gx4|5(!oxm;qq)|X`bw_V`bU(VnyyZc3M}MkhN3NQRUF(*JYC9l(`P1Og?HJ4k%Ay zB=?hOS6D7i6~iQG-p09Y&7?nG-!O$2@E+c$NvhOG{Buz z{l4u468ur5Um8xLQeJ{zh4%&cQz&j5z?gIopO$pV)aNLa|K{>fv^Vf?I{%uT=Qci@ zWM0{}lf)_#1_n<&UteA#iUqp|f_*Km26hp91SQyw3UV=#JWL@2L2@vgRxCsUi;+YN z?q_=dhj5Tp&VxLU5Ah^Ej7RY>PsO7g1ID6gkU~5r`b=SxQNbIQg`tv9~kFp_VcFyju8Fj(`IcLw@lHtrz>}=Xj_7+o-L738NL( zHN1p!g?@|`Qu#7Q;Q}f&wS!lNn3x2Uay~~u{q*8-jKSjs`vj)pNqz`9sjaJoXONwS zw(g*b2Y{=n(H1@ESoBH4@lsH;GH#n#a|%_#`iU1XPGcC~cEnHv zgKrO@ zb^RFK@D0?J&q^WKj{@T~hZ(oI!wvSZ_jF#ojYD`dXeSUS@Ex|_r8nQi47`P<{3N)X z9|I+3i{ZV7X+*7RR2Fa+oDT4Z2wc3n*a7}3X7{6naA&75X8?WyegQX}ZOsenCKo8C zDt=L%%p~Kc@(O!@%HFpTz|S=(CY5U#OHeC~#U_qq;bQswYv8&$gX@;lzbUS(#C46h z1`%LD30Xt9cwNiEbqv4l;OcT5eN%?7rhfRyQq#G-49#^hloe!Z6be--N>mv)arsb? zmFEW8$M8EN>Yiuoo|j+u{1J6ertScBPoeH<*U`;O$gkm#TQmMxaOOAk2e0CV>Sjz< zbLo$HIsWht^9QdgBXYv+CjO|)&q?!$oGd4T735?kIaz%jPCm&^Z>Q+#Of-_lEgon( z+i*{x=DX4dP$8dC8`$y|<)A&v6$PBJD44>+MHjJ%Iq9}mW3IQ-%ltW`()$#O8krhy zZ)=pCUg=F?@dYfAjw4>C(;qSmEFH>LQ{khEdr_cv5O@cwR41xc7pAD4{NE29n6GxF zsr(RSJhJ~lm0d+u)|TVF)iEc)Cn3Wps#92&Yf7A>{F>m*zMUqC@#Cu>M{%{-^E6B~ zfMQwAB)E78rp?45hf~8cR!NL2-h$IiPIj0ygVja~%X2k%|x+M_O;?s_=qEF3I&M~6jgzhDXc!r7q|PK)6@H% z>9=vRxKDd~&DjOsy0aX~r}|~8z6hWCT8`@DOmKGaWShJ;*W@=ijb8+u$yp}faUGMt zN4?*t$v?=^`veo1t#>(Xkn^!hN9;PDPfTEv=9>oKRYOkG6^df|RzK0QEO@S=f{x>6 z?4ztFnU+S9$h0I9=jD_54kf-jOyX0Nb%Mzz&5i9AhC@*bEoZWw;_>LoC!NVzPFZ(m zfj4l5BYB+SDMO)WG<+UA+YZIU)66Ee;(!x}zF>8EYYOXy4p%sMWQ*{Fj5B+c6NuwA zm95MI+@7`lFdGJ7^5>m7Yi5{YVOqRNF}HbI&T2 zcvkC$U!*vxMQ`Oo*>RN@v7x>8JT|sAUcjaxP0U)Zizm+}6nQpN#1@S4v}L85XEH(P zMzXn`wc(Z=Q8tneis{ryzLYVcKu52b(AGZrJnqW7Fv^87y-+r=nBdkpPi$|`yYL_v zKA;y$QjvwVjz4r>V`?t8-QXtd7%i6V^$gB9gxy1svdJog)iv2(ynDD8KTDz>(_Wk* zRk)?AaF)5^LM0xRs+{k9Jj)zDki+Sh9i0tKO`@|bSS{{t(C&5AxzT%$T*vk zQK%iQWo&4#qpMTMBjZKNNae^lmyzMZvAMlQJ2#JvZ&Jp$a%4Q8k>SG8)*jG)&LiVZ z%6KbB#tRu4E*$fO54t>$j2}_Pk8@;v#gXv@*$__eYGAxq^U9RB#&caI^g(!vK9EC@ z1^rgua%*(w35*Kri|_chfx%w{IhM7d^@Ygu4!oXsnW27(I?sE!!Sg;Ad47cz%)EDc zKExJ6kxG@^)K!!hWMSqPTqj_q{ua!m?F8=}$M>}9TaFzF`gk;oQD|5wHA=YfMWh^) zA9nWoB3?8{Gu{_6m&@sXoK*%(s(GwfwyooRPlirmTtofD6t)N1@V|TQOWzgOg-TyO zjcSw|HK;Hqp~jeunMMFjd^Q_XwLPQYEmt3)$i!1hZk_Hc7XQzKW7lR{C5ds0bCoOG zn!=7?c_@Vr)^ugt_{RI(xfY&blKv<1GLpWE*!JFxNyaUhY&1C}s_k|;a6VH^CTP2y z?{sq~?d)1dFNND%F9#c>EZND7-uT+N1>VNj#(OUjODU>}7W@n7r|aHhtc1^4MRHfu z;x$@f6}Xve^fi{d_$6HenRq$N+Kc#_yuD7%=Qbn@5TPq9tv1MY-j=6=#T(i=wEI5Vvm0sqo z`Z5~dUBiO3zRb^G^_7Je5YYlE`Hg3BjlAz_^Un1iVc9qMx@#t7N9x5P-SuQkw#<0% zdF;8Q{qiV|@oS7t)pmYWff0dW>_(BXhji^lr4dD~(TfJ-KHO*|7$iw7Hu|vA*oU>o ze%xssget and opt - * methods for accessing the values by index, and put methods for - * adding or replacing values. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the - * JSONObject.NULL object. - *

    - * The constructor can convert a JSON text into a Java object. The - * toString method converts to JSON text. - *

    - * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

    - * The generic get() and opt() methods return an - * object which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. - *

    - * The texts produced by the toString methods strictly conform to - * JSON syntax rules. The constructors are more forgiving in the texts they will - * accept: - *

      - *
    • An extra , (comma) may appear just - * before the closing bracket.
    • - *
    • The null value will be inserted when there is , - *  (comma) elision.
    • - *
    • Strings may be quoted with ' (single - * quote).
    • - *
    • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
    • - *
    • Values can be separated by ; (semicolon) as - * well as by , (comma).
    • - *
    - * - * @author JSON.org - * @version 2012-04-20 - */ -public class JSONArray { - - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * @param x A JSONTokener - * @throws JSONException If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); - } else { - x.back(); - this.myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); - } - } - } - } - - - /** - * Construct a JSONArray from a source JSON text. - * @param source A string that begins with - * [ (left bracket) - * and ends with ] (right bracket). - * @throws JSONException If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONArray from a Collection. - * @param collection A Collection. - */ - public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { - Iterator iter = collection.iterator(); - while (iter.hasNext()) { - this.myArrayList.add(JSONObject.wrap(iter.next())); - } - } - } - - - /** - * Construct a JSONArray from an array - * @throws JSONException If not an array. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( -"JSONArray initial value should be a string or collection or array."); - } - } - - - /** - * Get the object value associated with an index. - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with an index. - * The string values "true" and "false" are converted to boolean. - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException If there is no value for the index or if the - * value is not convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - - /** - * Get the double value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the int value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the JSONArray associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException If there is no value for the index. or if the - * value is not a JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject associated with an index. - * @param index subscript - * @return A JSONObject value. - * @throws JSONException If there is no value for the index or if the - * value is not a JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONArray[" + index + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot - * be converted to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] is not a number."); - } - } - - - /** - * Get the string associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - - /** - * Determine if the value is null. - * @param index The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. - * Warning: This method assumes that the data structure is acyclical. - * @param separator A string that will be inserted between the elements. - * @return a string. - * @throws JSONException If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - - /** - * Get the optional object value associated with an index. - * @param index The index must be between 0 and length() - 1. - * @return An object value, or null if there is no - * object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) - ? null - : this.myArrayList.get(index); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns false if there is no value at that index, - * or if the value is not Boolean.TRUE or the String "true". - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - - /** - * Get the optional boolean value associated with an index. - * It returns the defaultValue if there is no value at that index or if - * it is not a Boolean or the String "true" or "false" (case insensitive). - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional double value associated with an index. - * NaN is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.NaN); - } - - - /** - * Get the optional double value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index subscript - * @param defaultValue The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional int value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public int optInt(int index) { - return this.optInt(index, 0); - } - - - /** - * Get the optional int value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - try { - return this.getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional JSONArray associated with an index. - * @param index subscript - * @return A JSONArray value, or null if the index has no value, - * or if the value is not a JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get the optional JSONObject associated with an index. - * Null is returned if the key is not found, or null if the index has - * no value, or if the value is not a JSONObject. - * - * @param index The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject)o : null; - } - - - /** - * Get the optional long value associated with an index. - * Zero is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public long optLong(int index) { - return this.optLong(index, 0); - } - - - /** - * Get the optional long value associated with an index. - * The defaultValue is returned if there is no value for the index, - * or if the value is not a number and cannot be converted to a number. - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional string value associated with an index. It returns an - * empty string if there is no value at that index. If the value - * is not a string and is not null, then it is coverted to a string. - * - * @param index The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - - /** - * Get the optional string associated with an index. - * The defaultValue is returned if the key is not found. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) - ? defaultValue : object - .toString(); - } - - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - this.put(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param value A Collection value. - * @return this. - */ - public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; - } - - - /** - * Append a double value. This increases the array's length by one. - * - * @param value A double value. - * @throws JSONException if the value is not finite. - * @return this. - */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); - JSONObject.testValidity(d); - this.put(d); - return this; - } - - - /** - * Append an int value. This increases the array's length by one. - * - * @param value An int value. - * @return this. - */ - public JSONArray put(int value) { - this.put(new Integer(value)); - return this; - } - - - /** - * Append an long value. This increases the array's length by one. - * - * @param value A long value. - * @return this. - */ - public JSONArray put(long value) { - this.put(new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject which is produced from a Map. - * @param value A Map value. - * @return this. - */ - public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; - } - - - /** - * Append an object value. This increases the array's length by one. - * @param value An object value. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - */ - public JSONArray put(Object value) { - this.myArrayList.add(value); - return this; - } - - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value A boolean value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONArray which is produced from a Collection. - * @param index The subscript. - * @param value A Collection value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; - } - - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A double value. - * @return this. - * @throws JSONException If the index is negative or if the value is - * not finite. - */ - public JSONArray put(int index, double value) throws JSONException { - this.put(index, new Double(value)); - return this; - } - - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value An int value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - this.put(index, new Integer(value)); - return this; - } - - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad - * it out. - * @param index The subscript. - * @param value A long value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - this.put(index, new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a - * JSONObject that is produced from a Map. - * @param index The subscript. - * @param value The Map value. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * @param index The subscript. - * @param value The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - * @throws JSONException If the index is negative or if the the value is - * an invalid number. - */ - public JSONArray put(int index, Object value) throws JSONException { - JSONObject.testValidity(value); - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - this.myArrayList.set(index, value); - } else { - while (index != this.length()) { - this.put(JSONObject.NULL); - } - this.put(value); - } - return this; - } - - - /** - * Remove an index and close the hole. - * @param index The index of the element to be removed. - * @return The value that was associated with the index, - * or null if there was no value. - */ - public Object remove(int index) { - Object o = this.opt(index); - this.myArrayList.remove(index); - return o; - } - - - /** - * Produce a JSONObject by combining a JSONArray of names with the values - * of this JSONArray. - * @param names A JSONArray containing a list of key strings. These will be - * paired with the values. - * @return A JSONObject, or null if there are no names or if this JSONArray - * has no values. - * @throws JSONException If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { - return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - - /** - * Make a JSON text of this JSONArray. For compactness, no - * unnecessary whitespace is added. If it is not possible to produce a - * syntactically correct JSON text then null will be returned instead. This - * could occur if the array contains an invalid number. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, transmittable - * representation of the array. - */ - public String toString() { - try { - return '[' + this.join(",") + ']'; - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONArray. - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with [ (left bracket) and ending - * with ] (right bracket). - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indention of the top level. - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - int length = this.length(); - writer.write('['); - - if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), - indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, this.myArrayList.get(i), - indentFactor, newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); - } - } -} diff --git a/dot/org/json/JSONException.class b/dot/org/json/JSONException.class deleted file mode 100644 index 61db0afc1768f7283d4f622d95e48f1a1d7d75e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 587 zcmY*W%TB^T6g^WYm0CdFh_C31M*@jkj2qNMg17+L4>+kMwKaXHpQVY9#DyQ=M;UKx zL!pa1GpFZq@66Bd*EfJ;9H@{{QBg%LjU=`e)D`S7Y`MZQxH%P$YuMJ!NSDW7~J;;=%~b3WM?W z==^yu9y}VW6ZEPfgRFvG4SU$vunCQ!Vmo?w;o4Srjn7bwr(3$Lq03|nrtYqU>vElf zOKbf_bK{V%Jh(&&b)=wxMhZ`9LZ}hiCkUhdsOIQ&M7Tt2s@47kd!-${6je1u^W;?s z`T2<7iTK%8`vVe5TJ3ivVqKQ}fik65D5XlO0*aA#k5)#1<<=V#FUzP@2-c~V2$N9$ E18ksnod5s; diff --git a/dot/org/json/JSONException.java b/dot/org/json/JSONException.java deleted file mode 100755 index 289b602..0000000 --- a/dot/org/json/JSONException.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.json; - -/** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * @author JSON.org - * @version 2010-12-24 - */ -public class JSONException extends Exception { - private static final long serialVersionUID = 0; - private Throwable cause; - - /** - * Constructs a JSONException with an explanatory message. - * @param message Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } - - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } - - public Throwable getCause() { - return this.cause; - } -} diff --git a/dot/org/json/JSONML.java b/dot/org/json/JSONML.java deleted file mode 100755 index f29ee72..0000000 --- a/dot/org/json/JSONML.java +++ /dev/null @@ -1,467 +0,0 @@ -package org.json; - -/* -Copyright (c) 2008 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONArray or - * JSONObject, and to covert a JSONArray or JSONObject into an XML text using - * the JsonML transform. - * - * @author JSON.org - * @version 2012-03-28 - */ -public class JSONML { - - /** - * Parse XML values and store them in a JSONArray. - * @param x The XMLTokener containing the source string. - * @param arrayForm true if array form, false if object form. - * @param ja The JSONArray that is containing the current tag or null - * if we are at the outermost level. - * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException - */ - private static Object parse( - XMLTokener x, - boolean arrayForm, - JSONArray ja - ) throws JSONException { - String attribute; - char c; - String closeTag = null; - int i; - JSONArray newja = null; - JSONObject newjo = null; - Object token; - String tagName = null; - -// Test for and skip past these forms: -// -// -// -// - - while (true) { - if (!x.more()) { - throw x.syntaxError("Bad XML"); - } - token = x.nextContent(); - if (token == XML.LT) { - token = x.nextToken(); - if (token instanceof Character) { - if (token == XML.SLASH) { - -// Close tag "); - } else { - x.back(); - } - } else if (c == '[') { - token = x.nextToken(); - if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { - ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); - } - } else { - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - } - } else if (token == XML.QUEST) { - -// "); - } else { - throw x.syntaxError("Misshaped tag"); - } - -// Open tag < - - } else { - if (!(token instanceof String)) { - throw x.syntaxError("Bad tagName '" + token + "'."); - } - tagName = (String)token; - newja = new JSONArray(); - newjo = new JSONObject(); - if (arrayForm) { - newja.put(tagName); - if (ja != null) { - ja.put(newja); - } - } else { - newjo.put("tagName", tagName); - if (ja != null) { - ja.put(newjo); - } - } - token = null; - for (;;) { - if (token == null) { - token = x.nextToken(); - } - if (token == null) { - throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { - break; - } - -// attribute = value - - attribute = (String)token; - if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { - throw x.syntaxError("Reserved attribute."); - } - token = x.nextToken(); - if (token == XML.EQ) { - token = x.nextToken(); - if (!(token instanceof String)) { - throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String)token)); - token = null; - } else { - newjo.accumulate(attribute, ""); - } - } - if (arrayForm && newjo.length() > 0) { - newja.put(newjo); - } - -// Empty tag <.../> - - if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - -// Content, between <...> and - - } else { - if (token != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - closeTag = (String)parse(x, arrayForm, newja); - if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + - "' and '" + closeTag + "'"); - } - tagName = null; - if (!arrayForm && newja.length() > 0) { - newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - } - } - } - } else { - if (ja != null) { - ja.put(token instanceof String - ? XML.stringToValue((String)token) - : token); - } - } - } - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new XMLTokener(string)); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has - * attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child content and tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(XMLTokener x) throws JSONException { - return (JSONArray)parse(x, true, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param x An XMLTokener of the XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject)parse(x, false, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. - * @param string The XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - return toJSONObject(new XMLTokener(string)); - } - - - /** - * Reverse the JSONML transformation, making an XML text from a JSONArray. - * @param ja A JSONArray. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuffer sb = new StringBuffer(); - String tagName; - String value; - -// Emit = length) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - do { - object = ja.get(i); - i += 1; - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } - } - } while (i < length); - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } - - /** - * Reverse the JSONML transformation, making an XML text from a JSONObject. - * The JSONObject must contain a "tagName" property. If it has children, - * then it must have a "childNodes" property containing an array of objects. - * The other properties are attributes with string values. - * @param jo A JSONObject. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; - -//Emit '); - } else { - sb.append('>'); - length = ja.length(); - for (i = 0; i < length; i += 1) { - object = ja.get(i); - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } else { - sb.append(object.toString()); - } - } - } - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } -} diff --git a/dot/org/json/JSONObject$1.class b/dot/org/json/JSONObject$1.class deleted file mode 100644 index 64c0e8fc984702841f9e103c6212c0616f9c9baa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmX^0Z`VEs1_mPr9(D$Hb_Om+2Cm@z(xT*4x6GVWMh1SbV1GaVq^#8B61}X%vP7VW zYhH3resN}Ax^HSpMt%xA12-dsXns+;epYdQo<2goiXkHd10w^EXI@@vk#kOBadB!f zBZC0Q6#bmUymWntv5XADSTqYL0JSm!9R>o-K*#{(u`sX#X%+@HAjt{DTtGF9Af5mR E00_A(^Z)<= diff --git a/dot/org/json/JSONObject$Null.class b/dot/org/json/JSONObject$Null.class deleted file mode 100644 index eb7d3742de52026cd9f35e43bb555c3ab6ef82a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmZutJx{_=6g{s6S}IuNL!kJvIPj5(=!h{UBqkb!p~k_jU?s)+s%B?V)vV)m@7Z>fPSZ?uSj1vF}Ef8!+U`^X~x8r%qSbduZ**aZ(-|8VuaJd?CAtf$K`5wF^>v2Fsh&V`%G)CY zi5PnA3u>+U1SRr}i2Nc(|A{|fnJO{JarsaP>qt!nN`%5lPRp}Sk0~*dof1WO;UvPd a`S22QW6xD&2-8GeK@mu)^cO{xVEh6ptae}k diff --git a/dot/org/json/JSONObject.class b/dot/org/json/JSONObject.class deleted file mode 100644 index 0393352d40d455cdf8aa5094900778d208c22927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17385 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 S<|@O7Tmz6K?h{Q;_x}OfJSF%5 diff --git a/dot/org/json/JSONObject.java b/dot/org/json/JSONObject.java deleted file mode 100755 index ffe5315..0000000 --- a/dot/org/json/JSONObject.java +++ /dev/null @@ -1,1593 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; - -/** - * A JSONObject is an unordered collection of name/value pairs. Its external - * form is a string wrapped in curly braces with colons between the names and - * values, and commas between the values and names. The internal form is an - * object having get and opt methods for accessing the - * values by name, and put methods for adding or replacing values - * by name. The values can be any of these types: Boolean, - * JSONArray, JSONObject, Number, - * String, or the JSONObject.NULL object. A JSONObject - * constructor can be used to convert an external form JSON text into an - * internal form whose values can be retrieved with the get and - * opt methods, or to convert values into a JSON text using the - * put and toString methods. A get method - * returns a value if one can be found, and throws an exception if one cannot be - * found. An opt method returns a default value instead of throwing - * an exception, and so is useful for obtaining optional values. - *

    - * The generic get() and opt() methods return an - * object, which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. The opt methods differ from the get methods in that they do - * not throw. Instead, they return a specified value, such as null. - *

    - * The put methods add or replace values in an object. For example, - * - *

    - * myString = new JSONObject().put("JSON", "Hello, World!").toString();
    - * 
    - * - * produces the string {"JSON": "Hello, World"}. - *

    - * The texts produced by the toString methods strictly conform to - * the JSON syntax rules. The constructors are more forgiving in the texts they - * will accept: - *

      - *
    • An extra , (comma) may appear just - * before the closing brace.
    • - *
    • Strings may be quoted with ' (single - * quote).
    • - *
    • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , = ; # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
    • - *
    • Keys can be followed by = or => as well as by - * :.
    • - *
    • Values can be followed by ; (semicolon) as - * well as by , (comma).
    • - *
    - * - * @author JSON.org - * @version 2012-07-02 - */ -public class JSONObject { - - /** - * JSONObject.NULL is equivalent to the value that JavaScript calls null, - * whilst Java's null is equivalent to the value that JavaScript calls - * undefined. - */ - private static final class Null { - - /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. - * @return NULL. - */ - protected final Object clone() { - return this; - } - - /** - * A Null object is equal to the null value and to itself. - * @param object An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object - * or null. - */ - public boolean equals(Object object) { - return object == null || object == this; - } - - /** - * Get the "null" string value. - * @return The string "null". - */ - public String toString() { - return "null"; - } - } - - - /** - * The map where the JSONObject's properties are kept. - */ - private final Map map; - - - /** - * It is sometimes more convenient and less ambiguous to have a - * NULL object than to use Java's null value. - * JSONObject.NULL.equals(null) returns true. - * JSONObject.NULL.toString() returns "null". - */ - public static final Object NULL = new Null(); - - - /** - * Construct an empty JSONObject. - */ - public JSONObject() { - this.map = new HashMap(); - } - - - /** - * Construct a JSONObject from a subset of another JSONObject. - * An array of strings is used to identify the keys that should be copied. - * Missing keys are ignored. - * @param jo A JSONObject. - * @param names An array of strings. - * @throws JSONException - * @exception JSONException If a value is a non-finite number or if a name is duplicated. - */ - public JSONObject(JSONObject jo, String[] names) { - this(); - for (int i = 0; i < names.length; i += 1) { - try { - this.putOnce(names[i], jo.opt(names[i])); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a JSONTokener. - * @param x A JSONTokener object containing the source string. - * @throws JSONException If there is a syntax error in the source string - * or a duplicated key. - */ - public JSONObject(JSONTokener x) throws JSONException { - this(); - char c; - String key; - - if (x.nextClean() != '{') { - throw x.syntaxError("A JSONObject text must begin with '{'"); - } - for (;;) { - c = x.nextClean(); - switch (c) { - case 0: - throw x.syntaxError("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); - } - -// The key is followed by ':'. We will also tolerate '=' or '=>'. - - c = x.nextClean(); - if (c == '=') { - if (x.next() != '>') { - x.back(); - } - } else if (c != ':') { - throw x.syntaxError("Expected a ':' after a key"); - } - this.putOnce(key, x.nextValue()); - -// Pairs are separated by ','. We will also tolerate ';'. - - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { - return; - } - x.back(); - break; - case '}': - return; - default: - throw x.syntaxError("Expected a ',' or '}'"); - } - } - } - - - /** - * Construct a JSONObject from a Map. - * - * @param map A map object that can be used to initialize the contents of - * the JSONObject. - * @throws JSONException - */ - public JSONObject(Map map) { - this.map = new HashMap(); - if (map != null) { - Iterator i = map.entrySet().iterator(); - while (i.hasNext()) { - Map.Entry e = (Map.Entry)i.next(); - Object value = e.getValue(); - if (value != null) { - this.map.put(e.getKey(), wrap(value)); - } - } - } - } - - - /** - * Construct a JSONObject from an Object using bean getters. - * It reflects on all of the public methods of the object. - * For each of the methods with no parameters and a name starting - * with "get" or "is" followed by an uppercase letter, - * the method is invoked, and a key and the value returned from the getter method - * are put into the new JSONObject. - * - * The key is formed by removing the "get" or "is" prefix. - * If the second remaining character is not upper case, then the first - * character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is "Larry Fine", - * then the JSONObject will contain "name": "Larry Fine". - * - * @param bean An object that has getter methods that should be used - * to make a JSONObject. - */ - public JSONObject(Object bean) { - this(); - this.populateMap(bean); - } - - - /** - * Construct a JSONObject from an Object, using reflection to find the - * public members. The resulting JSONObject's keys will be the strings - * from the names array, and the values will be the field values associated - * with those keys in the object. If a key is not found or not visible, - * then it will not be copied into the new JSONObject. - * @param object An object that has fields that should be used to make a - * JSONObject. - * @param names An array of strings, the names of the fields to be obtained - * from the object. - */ - public JSONObject(Object object, String names[]) { - this(); - Class c = object.getClass(); - for (int i = 0; i < names.length; i += 1) { - String name = names[i]; - try { - this.putOpt(name, c.getField(name).get(object)); - } catch (Exception ignore) { - } - } - } - - - /** - * Construct a JSONObject from a source JSON text string. - * This is the most commonly used JSONObject constructor. - * @param source A string beginning - * with { (left brace) and ending - * with } (right brace). - * @exception JSONException If there is a syntax error in the source - * string or a duplicated key. - */ - public JSONObject(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONObject from a ResourceBundle. - * @param baseName The ResourceBundle base name. - * @param locale The Locale to load the ResourceBundle for. - * @throws JSONException If any JSONExceptions are detected. - */ - public JSONObject(String baseName, Locale locale) throws JSONException { - this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, - Thread.currentThread().getContextClassLoader()); - -// Iterate through the keys in the bundle. - - Enumeration keys = bundle.getKeys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - if (key instanceof String) { - -// Go through the path, ensuring that there is a nested JSONObject for each -// segment except the last. Add the value using the last segment's name into -// the deepest nested JSONObject. - - String[] path = ((String)key).split("\\."); - int last = path.length - 1; - JSONObject target = this; - for (int i = 0; i < last; i += 1) { - String segment = path[i]; - JSONObject nextTarget = target.optJSONObject(segment); - if (nextTarget == null) { - nextTarget = new JSONObject(); - target.put(segment, nextTarget); - } - target = nextTarget; - } - target.put(path[last], bundle.getString((String)key)); - } - } - } - - - /** - * Accumulate values under a key. It is similar to the put method except - * that if there is already an object stored under the key then a - * JSONArray is stored under the key to hold all of the accumulated values. - * If there is already a JSONArray, then the new value is appended to it. - * In contrast, the put method replaces the previous value. - * - * If only one value is accumulated that is not a JSONArray, then the - * result will be the same as using put. But if multiple values are - * accumulated, then the result will be like append. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the value is an invalid number - * or if the key is null. - */ - public JSONObject accumulate( - String key, - Object value - ) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, value instanceof JSONArray - ? new JSONArray().put(value) - : value); - } else if (object instanceof JSONArray) { - ((JSONArray)object).put(value); - } else { - this.put(key, new JSONArray().put(object).put(value)); - } - return this; - } - - - /** - * Append values to the array under a key. If the key does not exist in the - * JSONObject, then the key is put in the JSONObject with its value being a - * JSONArray containing the value parameter. If the key was already - * associated with a JSONArray, then the value parameter is appended to it. - * @param key A key string. - * @param value An object to be accumulated under the key. - * @return this. - * @throws JSONException If the key is null or if the current value - * associated with the key is not a JSONArray. - */ - public JSONObject append(String key, Object value) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, new JSONArray().put(value)); - } else if (object instanceof JSONArray) { - this.put(key, ((JSONArray)object).put(value)); - } else { - throw new JSONException("JSONObject[" + key + - "] is not a JSONArray."); - } - return this; - } - - - /** - * Produce a string from a double. The string "null" will be returned if - * the number is not finite. - * @param d A double. - * @return A String. - */ - public static String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { - return "null"; - } - -// Shave off trailing zeros and decimal point, if possible. - - String string = Double.toString(d); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get the value object associated with a key. - * - * @param key A key string. - * @return The object associated with the key. - * @throws JSONException if the key is not found. - */ - public Object get(String key) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - Object object = this.opt(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + - "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with a key. - * - * @param key A key string. - * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) || - (object instanceof String && - ((String)object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a Boolean."); - } - - - /** - * Get the double value associated with a key. - * @param key A key string. - * @return The numeric value. - * @throws JSONException if the key is not found or - * if the value is not a Number object and cannot be converted to a number. - */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).doubleValue() - : Double.parseDouble((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a number."); - } - } - - - /** - * Get the int value associated with a key. - * - * @param key A key string. - * @return The integer value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to an integer. - */ - public int getInt(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).intValue() - : Integer.parseInt((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not an int."); - } - } - - - /** - * Get the JSONArray value associated with a key. - * - * @param key A key string. - * @return A JSONArray which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONArray. - */ - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONArray."); - } - - - /** - * Get the JSONObject value associated with a key. - * - * @param key A key string. - * @return A JSONObject which is the value. - * @throws JSONException if the key is not found or - * if the value is not a JSONObject. - */ - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] is not a JSONObject."); - } - - - /** - * Get the long value associated with a key. - * - * @param key A key string. - * @return The long value. - * @throws JSONException if the key is not found or if the value cannot - * be converted to a long. - */ - public long getLong(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number - ? ((Number)object).longValue() - : Long.parseLong((String)object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + - "] is not a long."); - } - } - - - /** - * Get an array of field names from a JSONObject. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(JSONObject jo) { - int length = jo.length(); - if (length == 0) { - return null; - } - Iterator iterator = jo.keys(); - String[] names = new String[length]; - int i = 0; - while (iterator.hasNext()) { - names[i] = (String)iterator.next(); - i += 1; - } - return names; - } - - - /** - * Get an array of field names from an Object. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(Object object) { - if (object == null) { - return null; - } - Class klass = object.getClass(); - Field[] fields = klass.getFields(); - int length = fields.length; - if (length == 0) { - return null; - } - String[] names = new String[length]; - for (int i = 0; i < length; i += 1) { - names[i] = fields[i].getName(); - } - return names; - } - - - /** - * Get the string associated with a key. - * - * @param key A key string. - * @return A string which is the value. - * @throws JSONException if there is no string value for the key. - */ - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String)object; - } - throw new JSONException("JSONObject[" + quote(key) + - "] not a string."); - } - - - /** - * Determine if the JSONObject contains a specific key. - * @param key A key string. - * @return true if the key exists in the JSONObject. - */ - public boolean has(String key) { - return this.map.containsKey(key); - } - - - /** - * Increment a property of a JSONObject. If there is no such property, - * create one with a value of 1. If there is such a property, and if - * it is an Integer, Long, Double, or Float, then add one to it. - * @param key A key string. - * @return this. - * @throws JSONException If there is already a property with this name - * that is not an Integer, Long, Double, or Float. - */ - public JSONObject increment(String key) throws JSONException { - Object value = this.opt(key); - if (value == null) { - this.put(key, 1); - } else if (value instanceof Integer) { - this.put(key, ((Integer)value).intValue() + 1); - } else if (value instanceof Long) { - this.put(key, ((Long)value).longValue() + 1); - } else if (value instanceof Double) { - this.put(key, ((Double)value).doubleValue() + 1); - } else if (value instanceof Float) { - this.put(key, ((Float)value).floatValue() + 1); - } else { - throw new JSONException("Unable to increment [" + quote(key) + "]."); - } - return this; - } - - - /** - * Determine if the value associated with the key is null or if there is - * no value. - * @param key A key string. - * @return true if there is no value associated with the key or if - * the value is the JSONObject.NULL object. - */ - public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); - } - - - /** - * Get an enumeration of the keys of the JSONObject. - * - * @return An iterator of the keys. - */ - public Iterator keys() { - return this.map.keySet().iterator(); - } - - - /** - * Get the number of keys stored in the JSONObject. - * - * @return The number of keys in the JSONObject. - */ - public int length() { - return this.map.size(); - } - - - /** - * Produce a JSONArray containing the names of the elements of this - * JSONObject. - * @return A JSONArray containing the key strings, or null if the JSONObject - * is empty. - */ - public JSONArray names() { - JSONArray ja = new JSONArray(); - Iterator keys = this.keys(); - while (keys.hasNext()) { - ja.put(keys.next()); - } - return ja.length() == 0 ? null : ja; - } - - /** - * Produce a string from a Number. - * @param number A Number - * @return A String. - * @throws JSONException If n is a non-finite number. - */ - public static String numberToString(Number number) - throws JSONException { - if (number == null) { - throw new JSONException("Null pointer"); - } - testValidity(number); - -// Shave off trailing zeros and decimal point, if possible. - - String string = number.toString(); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && - string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - - /** - * Get an optional value associated with a key. - * @param key A key string. - * @return An object which is the value, or null if there is no value. - */ - public Object opt(String key) { - return key == null ? null : this.map.get(key); - } - - - /** - * Get an optional boolean associated with a key. - * It returns false if there is no such key, or if the value is not - * Boolean.TRUE or the String "true". - * - * @param key A key string. - * @return The truth. - */ - public boolean optBoolean(String key) { - return this.optBoolean(key, false); - } - - - /** - * Get an optional boolean associated with a key. - * It returns the defaultValue if there is no such key, or if it is not - * a Boolean or the String "true" or "false" (case insensitive). - * - * @param key A key string. - * @param defaultValue The default. - * @return The truth. - */ - public boolean optBoolean(String key, boolean defaultValue) { - try { - return this.getBoolean(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional double associated with a key, - * or NaN if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A string which is the key. - * @return An object which is the value. - */ - public double optDouble(String key) { - return this.optDouble(key, Double.NaN); - } - - - /** - * Get an optional double associated with a key, or the - * defaultValue if there is no such key or if its value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public double optDouble(String key, double defaultValue) { - try { - return this.getDouble(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional int value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public int optInt(String key) { - return this.optInt(key, 0); - } - - - /** - * Get an optional int value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public int optInt(String key, int defaultValue) { - try { - return this.getInt(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional JSONArray associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONArray. - * - * @param key A key string. - * @return A JSONArray which is the value. - */ - public JSONArray optJSONArray(String key) { - Object o = this.opt(key); - return o instanceof JSONArray ? (JSONArray)o : null; - } - - - /** - * Get an optional JSONObject associated with a key. - * It returns null if there is no such key, or if its value is not a - * JSONObject. - * - * @param key A key string. - * @return A JSONObject which is the value. - */ - public JSONObject optJSONObject(String key) { - Object object = this.opt(key); - return object instanceof JSONObject ? (JSONObject)object : null; - } - - - /** - * Get an optional long value associated with a key, - * or zero if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @return An object which is the value. - */ - public long optLong(String key) { - return this.optLong(key, 0); - } - - - /** - * Get an optional long value associated with a key, - * or the default if there is no such key or if the value is not a number. - * If the value is a string, an attempt will be made to evaluate it as - * a number. - * - * @param key A key string. - * @param defaultValue The default. - * @return An object which is the value. - */ - public long optLong(String key, long defaultValue) { - try { - return this.getLong(key); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get an optional string associated with a key. - * It returns an empty string if there is no such key. If the value is not - * a string and is not null, then it is converted to a string. - * - * @param key A key string. - * @return A string which is the value. - */ - public String optString(String key) { - return this.optString(key, ""); - } - - - /** - * Get an optional string associated with a key. - * It returns the defaultValue if there is no such key. - * - * @param key A key string. - * @param defaultValue The default. - * @return A string which is the value. - */ - public String optString(String key, String defaultValue) { - Object object = this.opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); - } - - - private void populateMap(Object bean) { - Class klass = bean.getClass(); - -// If klass is a System class then set includeSuperClass to false. - - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass - ? klass.getMethods() - : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || - "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && - Character.isUpperCase(key.charAt(0)) && - method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + - key.substring(1); - } - - Object result = method.invoke(bean, (Object[])null); - if (result != null) { - this.map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - } - - - /** - * Put a key/boolean pair in the JSONObject. - * - * @param key A key string. - * @param value A boolean which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, boolean value) throws JSONException { - this.put(key, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONArray which is produced from a Collection. - * @param key A key string. - * @param value A Collection value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Collection value) throws JSONException { - this.put(key, new JSONArray(value)); - return this; - } - - - /** - * Put a key/double pair in the JSONObject. - * - * @param key A key string. - * @param value A double which is the value. - * @return this. - * @throws JSONException If the key is null or if the number is invalid. - */ - public JSONObject put(String key, double value) throws JSONException { - this.put(key, new Double(value)); - return this; - } - - - /** - * Put a key/int pair in the JSONObject. - * - * @param key A key string. - * @param value An int which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, int value) throws JSONException { - this.put(key, new Integer(value)); - return this; - } - - - /** - * Put a key/long pair in the JSONObject. - * - * @param key A key string. - * @param value A long which is the value. - * @return this. - * @throws JSONException If the key is null. - */ - public JSONObject put(String key, long value) throws JSONException { - this.put(key, new Long(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONObject which is produced from a Map. - * @param key A key string. - * @param value A Map value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Map value) throws JSONException { - this.put(key, new JSONObject(value)); - return this; - } - - - /** - * Put a key/value pair in the JSONObject. If the value is null, - * then the key will be removed from the JSONObject if it is present. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is non-finite number - * or if the key is null. - */ - public JSONObject put(String key, Object value) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - if (value != null) { - testValidity(value); - this.map.put(key, value); - } else { - this.remove(key); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the key and the - * value are both non-null, and only if there is not already a member - * with that name. - * @param key - * @param value - * @return his. - * @throws JSONException if the key is a duplicate - */ - public JSONObject putOnce(String key, Object value) throws JSONException { - if (key != null && value != null) { - if (this.opt(key) != null) { - throw new JSONException("Duplicate key \"" + key + "\""); - } - this.put(key, value); - } - return this; - } - - - /** - * Put a key/value pair in the JSONObject, but only if the - * key and the value are both non-null. - * @param key A key string. - * @param value An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, - * or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the value is a non-finite number. - */ - public JSONObject putOpt(String key, Object value) throws JSONException { - if (key != null && value != null) { - this.put(key, value); - } - return this; - } - - - /** - * Produce a string in double quotes with backslash sequences in all the - * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - hhhh = "000" + Integer.toHexString(c); - w.write("\\u" + hhhh.substring(hhhh.length() - 4)); - } else { - w.write(c); - } - } - } - w.write('"'); - return w; - } - - /** - * Remove a name and its value, if present. - * @param key The name to be removed. - * @return The value that was associated with the name, - * or null if there was no value. - */ - public Object remove(String key) { - return this.map.remove(key); - } - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - Double d; - if (string.equals("")) { - return string; - } - if (string.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { - return JSONObject.NULL; - } - - /* - * If it might be a number, try converting it. - * If a number cannot be produced, then the value will just - * be a string. Note that the plus and implied string - * conventions are non-standard. A JSON parser may accept - * non-JSON forms as long as it accepts all correct JSON forms. - */ - - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { - try { - if (string.indexOf('.') > -1 || - string.indexOf('e') > -1 || string.indexOf('E') > -1) { - d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { - return d; - } - } else { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } catch (Exception ignore) { - } - } - return string; - } - - - /** - * Throw an exception if the object is a NaN or infinite number. - * @param o The object to test. - * @throws JSONException If o is a non-finite number. - */ - public static void testValidity(Object o) throws JSONException { - if (o != null) { - if (o instanceof Double) { - if (((Double)o).isInfinite() || ((Double)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float)o).isInfinite() || ((Float)o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } - } - } - - - /** - * Produce a JSONArray containing the values of the members of this - * JSONObject. - * @param names A JSONArray containing a list of key strings. This - * determines the sequence of the values in the result. - * @return A JSONArray of values. - * @throws JSONException If any of the values are non-finite numbers. - */ - public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (int i = 0; i < names.length(); i += 1) { - ja.put(this.opt(names.getString(i))); - } - return ja; - } - - /** - * Make a JSON text of this JSONObject. For compactness, no whitespace - * is added. If this would not result in a syntactically correct JSON text, - * then null will be returned instead. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - */ - public String toString() { - try { - return this.toString(0); - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

    - * Warning: This method assumes that the data structure is acyclical. - * @param indentFactor The number of spaces to add to each level of - * indentation. - * @return a printable, displayable, portable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the object contains an invalid number. - */ - public String toString(int indentFactor) throws JSONException { - StringWriter w = new StringWriter(); - synchronized (w.getBuffer()) { - return this.write(w, indentFactor, 0).toString(); - } - } - - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce - * the JSON text. The method is required to produce a strictly - * conforming text. If the object does not contain a toJSONString - * method (which is the most common case), then a text will be - * produced by other means. If the value is an array or Collection, - * then a JSONArray will be made from it and its toJSONString method - * will be called. If the value is a MAP, then a JSONObject will be made - * from it and its toJSONString method will be called. Otherwise, the - * value's toString method will be called, and the result will be quoted. - * - *

    - * Warning: This method assumes that the data structure is acyclical. - * @param value The value to be serialized. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - * @throws JSONException If the value is or contains an invalid number. - */ - public static String valueToString(Object value) throws JSONException { - if (value == null || value.equals(null)) { - return "null"; - } - if (value instanceof JSONString) { - Object object; - try { - object = ((JSONString)value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - if (object instanceof String) { - return (String)object; - } - throw new JSONException("Bad value from toJSONString: " + object); - } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean || value instanceof JSONObject || - value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - return new JSONObject((Map)value).toString(); - } - if (value instanceof Collection) { - return new JSONArray((Collection)value).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); - } - return quote(value.toString()); - } - - /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If - * it is a map, wrap it in a JSONObject. If it is a standard property - * (Double, String, et al) then it is already wrapped. Otherwise, if it - * comes from one of the java packages, turn it into a string. And if - * it doesn't, try to wrap it in a JSONObject. If the wrapping fails, - * then null is returned. - * - * @param object The object to wrap - * @return The wrapped value - */ - public static Object wrap(Object object) { - try { - if (object == null) { - return NULL; - } - if (object instanceof JSONObject || object instanceof JSONArray || - NULL.equals(object) || object instanceof JSONString || - object instanceof Byte || object instanceof Character || - object instanceof Short || object instanceof Integer || - object instanceof Long || object instanceof Boolean || - object instanceof Float || object instanceof Double || - object instanceof String || object instanceof Enum) { - return object; - } - - if (object instanceof Collection) { - return new JSONArray((Collection)object); - } - if (object.getClass().isArray()) { - return new JSONArray(object); - } - if (object instanceof Map) { - return new JSONObject((Map)object); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null - ? objectPackage.getName() - : ""; - if ( - objectPackageName.startsWith("java.") || - objectPackageName.startsWith("javax.") || - object.getClass().getClassLoader() == null - ) { - return object.toString(); - } - return new JSONObject(object); - } catch(Exception exception) { - return null; - } - } - - - /** - * Write the contents of the JSONObject as JSON text to a writer. - * For compactness, no whitespace is added. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - - static final Writer writeValue(Writer writer, Object value, - int indentFactor, int indent) throws JSONException, IOException { - if (value == null || value.equals(null)) { - writer.write("null"); - } else if (value instanceof JSONObject) { - ((JSONObject) value).write(writer, indentFactor, indent); - } else if (value instanceof JSONArray) { - ((JSONArray) value).write(writer, indentFactor, indent); - } else if (value instanceof Map) { - new JSONObject((Map) value).write(writer, indentFactor, indent); - } else if (value instanceof Collection) { - new JSONArray((Collection) value).write(writer, indentFactor, - indent); - } else if (value.getClass().isArray()) { - new JSONArray(value).write(writer, indentFactor, indent); - } else if (value instanceof Number) { - writer.write(numberToString((Number) value)); - } else if (value instanceof Boolean) { - writer.write(value.toString()); - } else if (value instanceof JSONString) { - Object o; - try { - o = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - writer.write(o != null ? o.toString() : quote(value.toString())); - } else { - quote(value.toString(), writer); - } - return writer; - } - - static final void indent(Writer writer, int indent) throws IOException { - for (int i = 0; i < indent; i += 1) { - writer.write(' '); - } - } - - /** - * Write the contents of the JSONObject as JSON text to a writer. For - * compactness, no whitespace is added. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - final int length = this.length(); - Iterator keys = this.keys(); - writer.write('{'); - - if (length == 1) { - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - while (keys.hasNext()) { - Object key = keys.next(); - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, newindent); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, - newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, indent); - } - writer.write('}'); - return writer; - } catch (IOException exception) { - throw new JSONException(exception); - } - } -} diff --git a/dot/org/json/JSONString.class b/dot/org/json/JSONString.class deleted file mode 100644 index 329f686758d463a599abfa28eaaca9bd9cbc1e45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156 zcmX^0Z`VEs1_mPrPId-%b_Nbc2A-09uV8<_;F6-uymUqe5e-eBti-ZJ{hY+SbbW}Z zH6sI8aDHh~a;jTqPAVeJSONString interface allows a toJSONString() - * method so that a class can change the behavior of - * JSONObject.toString(), JSONArray.toString(), - * and JSONWriter.value(Object). The - * toJSONString method will be used instead of the default behavior - * of using the Object's toString() method and quoting the result. - */ -public interface JSONString { - /** - * The toJSONString method allows a class to produce its own JSON - * serialization. - * - * @return A strictly syntactically correct JSON text. - */ - public String toJSONString(); -} diff --git a/dot/org/json/JSONStringer.java b/dot/org/json/JSONStringer.java deleted file mode 100755 index 25c2e5d..0000000 --- a/dot/org/json/JSONStringer.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.json; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.StringWriter; - -/** - * JSONStringer provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONStringer can produce one JSON text. - *

    - * A JSONStringer instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting cascade style. For example,

    - * myString = new JSONStringer()
    - *     .object()
    - *         .key("JSON")
    - *         .value("Hello, World!")
    - *     .endObject()
    - *     .toString();
    which produces the string
    - * {"JSON":"Hello, World!"}
    - *

    - * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONStringer adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

    - * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2008-09-18 - */ -public class JSONStringer extends JSONWriter { - /** - * Make a fresh JSONStringer. It can be used to build one JSON text. - */ - public JSONStringer() { - super(new StringWriter()); - } - - /** - * Return the JSON text. This method is used to obtain the product of the - * JSONStringer instance. It will return null if there was a - * problem in the construction of the JSON text (such as the calls to - * array were not properly balanced with calls to - * endArray). - * @return The JSON text. - */ - public String toString() { - return this.mode == 'd' ? this.writer.toString() : null; - } -} diff --git a/dot/org/json/JSONTokener.class b/dot/org/json/JSONTokener.class deleted file mode 100644 index f886bccd67a198d4bf1ea742ab6390dc08d47cae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5033 zcmai1X>^p;8GddulW*qBOc;iMz$7pP1IdsOM3F6QiJ(COXh1}yI>~&5fn;W!g+-(m z_iAlj(XdFsB`&ds76xh*YFBG(wYI0r@$^r7y7#od{A01{^WN{v#>qLIbMAYW@80)) z-u2%3;JY*M_!Qrgly?HaT2FIcu`h(s1h#;d0D=_BBaN_t0u0- zYX)97u>h}m@P_Q@_25le|7Ib^HLMh9Zwcv>GtYT&T0nfugKv9q#)Gp4@&?W+c-wYH z)6ur9l~zz|6$-874vub9aK{rdYoCIvBc8AnJgKy`C!Wk@__a}?C~ZY!awxEFS9DLb zE}pErS+6WrD9&Z9jYGSO>f?!ccDcfYs>`=l-$M3{$r#y>TSqDDbDgbLdQ-HugDd`) zY_x56b2O#r8t-{hg~`Kwni8p8wk1m}olAw8xq4rlmCDAG3BsJ{?CXdo+UvL}o@m#b zT&?6wO{?UDH)id$_K6V)rK+*INlcK4>CZHRt23D<7FWXBm(^>Hbho{eMwnRDRBh`t zQig%=kguF*?69Hq6pQr(&{r6kksb-OajMBUn!4eN)@NiLpja!`lSavalA z&z58^-Da(ci~9m{ep7O{m9WxtB}9C<3EK^v_u*|s6($XaO+#+S4l8ZN?C_CYH~X+2 z8+^C{O+IWCvJTBYti|;{tPye}u2+~c$Y4Ye4D;AZYYc9%0SX~U51M5T8X zuF#)G1WH3L-l0>7QJbQttXO!q4;OGz$al$Wb~u`dh2seVh{nR1=-%*bCLj0Yu*ZiC z7?GeVExFc=j_z=4GM9*D!j|pdz~ur3$a{m99|c4_K!KYRtOK3#L{zZYJO#`5MAvo$ z-}m7M_#tz(siVVck9LHuOj|T%&Gq3&0_ewh--oyuWfz!V6GoZX4n{%n6NTWYPpi`D z=zaxX&64d0>u#^uc3|nUnLd1gpRxut$1@pm#vTc9AAW`pefT*(^5J7_XBvj1*{~q| z1&@cf4VAJmV?Hcpivz`drK99ILCFvuHjoWZp=8j1cC;uIY-67LJEQ5{ErXt?+%z4c z%K^*9U^&tT-Lx~E+$;4Wn&eI;m_`>ZH-dALSt_e zZ<5LQVg5~YY`eJFlZvJ@7N-n@F)%er{c|yxIu#6E|2Ob9aIwsBeM;53vFvDTYTcEK zc3fU`oeEUVLh84}X;acERsXNV4HYk!*xtrKjooQ0V-b8=)!LDzZnXU{gIC^aJ_8IC zNWtK!K#Ga(Sw(cu8lroa7TvSr=$`e4eUOR8LPXla*>SkY0ay|_2NjuicNgk=b0IWO-Oh+rk^ zunO0pfnOW3nY$`cFn|CG4BTR13zUId2Sh1n&i+=tPN-W6P@q;jQ2mj9_yn8(97;sG zf=D;D9&7o=xe>QN*O3gy34_2G3^tL$W*%VSbL3{==A4Q}&cHYVA3Lx2 znd9*HWBk@&@Ej&wjBMqaX^CApGG$~&XgY1MqG1b7ql&QUO5+zdui(iC?<5=(1z$(44MlURsg{WTGp%=Eq zdJB4aut1y2hLNPEDVivaa#q|5mfpG8Ln!++3^xkL2LhDFYrv7dkiAGRr3H$*P-5G| zaP`1dILy3A@43feQV?7zhg!+R_Tp;JY$kb>Zi(bEu?z0PUJfR?hM7#F&4GtVA12C2 zP=ZGpxQ}V3g-|6U?4xMEn9W>W$peKv_=G^~Lck8%Gw{^+U?$hxd0fGvzgb*Ya}HB3 zhK}2wDk`kEofs7-@utUTb$GKR~&1?%L216a{DYh2C*D7cMUkox-%5azV4% z4ihsHyix={P^fwa{@9O7ap9~!QBa3)jd zZ~R;JcP7<8wFLQdb_pfwbNYW|P2wxU=C68e-Ib>wvuWz8^|tljAZz@EP3$7S2%Bgp zz2E6?XMa^BSS>agag5Pn@2z0p%{JTV>zrQBb+fgyZDZTPwx2D*mSjt_-OrX~v)FQM zkJkn~c|^AK3`A=KUVF5qHelML=GuVI9yQhm{Pt*ZZN$i9P9Sg|HBZ?~vuYVT!lOJA ztkt0t>V}7-xqX9QBm!-3wlY_MFW|ud{Hz#@lnX0V5w7E1(XG7bQ6^qjKAcv5oKfS@ zuL8KBf_%kI!24<G+qLfzMPWK3B6apsKWwD&ZF)208|K zOSvRfD4_!=`Va2($}i|C8l5zqgYKi53bc!sI__&0KQMGpU_yBp#+3)m6Y!QxEs?pw zuaj!1ZXR`gHOwEe#m7S$R}co&0(jIyYP<*)YB6T1C5Whc%vZ~4ffX8Y30#-pA;wFX zq6}kHWOdSucAs``-ogT zrS&}nf0pBp&dtG@^v$9!7Vh9;iO!nySTbB)8hC3%wZg3|ma?6=R_($PwHuA9lmFQg z*r@Ktt?B^U)jjA`2a!|vV!t|sL+U;}s_w^=>OpOz3K&ug-9FzJ3_5zTY=EyN9d`zj zI`T$&G(A+IKcl7Og|(SiinoEpT<9h(UTBcIgG=+M7qym^9YMLQ9bM<^&PNs<)bZ;l(8kRGtr>XceC|1v6ygH1j z>Um68U6`qkFg%Z_Ull; zO4Mo2_z%-zv5xkXr^q#f*W3y@Puu3PGPuefn=)>&$Hg*kw3%Pdxu2Z&l2-xt{SQMp B8wLOX diff --git a/dot/org/json/JSONTokener.java b/dot/org/json/JSONTokener.java deleted file mode 100644 index 13c84f1..0000000 --- a/dot/org/json/JSONTokener.java +++ /dev/null @@ -1,446 +0,0 @@ -package org.json; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. - * @author JSON.org - * @version 2012-02-16 - */ -public class JSONTokener { - - private long character; - private boolean eof; - private long index; - private long line; - private char previous; - private Reader reader; - private boolean usePrevious; - - - /** - * Construct a JSONTokener from a Reader. - * - * @param reader A reader. - */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader - : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; - } - - - /** - * Construct a JSONTokener from an InputStream. - */ - public JSONTokener(InputStream inputStream) throws JSONException { - this(new InputStreamReader(inputStream)); - } - - - /** - * Construct a JSONTokener from a string. - * - * @param s A source string. - */ - public JSONTokener(String s) { - this(new StringReader(s)); - } - - - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. - */ - public void back() throws JSONException { - if (this.usePrevious || this.index <= 0) { - throw new JSONException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; - } - - - /** - * Get the hex value of a character (base16). - * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. - */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { - return c - ('a' - 10); - } - return -1; - } - - public boolean end() { - return this.eof && !this.usePrevious; - } - - - /** - * Determine if the source string still contains characters that next() - * can consume. - * @return true if not yet at the end of the source. - */ - public boolean more() throws JSONException { - this.next(); - if (this.end()) { - return false; - } - this.back(); - return true; - } - - - /** - * Get the next character in the source string. - * - * @return The next character, or 0 if past the end of the source string. - */ - public char next() throws JSONException { - int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { - try { - c = this.reader.read(); - } catch (IOException exception) { - throw new JSONException(exception); - } - - if (c <= 0) { // End of stream - this.eof = true; - c = 0; - } - } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; - } - this.previous = (char) c; - return this.previous; - } - - - /** - * Consume the next character, and check that it matches a specified - * character. - * @param c The character to match. - * @return The character. - * @throws JSONException if the character does not match. - */ - public char next(char c) throws JSONException { - char n = this.next(); - if (n != c) { - throw this.syntaxError("Expected '" + c + "' and instead saw '" + - n + "'"); - } - return n; - } - - - /** - * Get the next n characters. - * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. - */ - public String next(int n) throws JSONException { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw this.syntaxError("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - - - /** - * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. - */ - public char nextClean() throws JSONException { - for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { - return c; - } - } - } - - - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string. - */ - public String nextString(char quote) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw this.syntaxError("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); - } - } - } - - - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. - */ - public String nextTo(char delimiter) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = this.next(); - if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the text up but not including one of the specified delimiter - * characters or the end of line, whichever comes first. - * @param delimiters A set of delimiter characters. - * @return A string, trimmed. - */ - public String nextTo(String delimiters) throws JSONException { - char c; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the next value. The value can be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. - * - * @return An object. - */ - public Object nextValue() throws JSONException { - char c = this.nextClean(); - String string; - - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - this.back(); - return new JSONObject(this); - case '[': - this.back(); - return new JSONArray(this); - } - - /* - * Handle unquoted text. This could be the values true, false, or - * null, or it can be a number. An implementation (such as this one) - * is allowed to also accept non-standard forms. - * - * Accumulate characters until we reach the end of the text or a - * formatting character. - */ - - StringBuffer sb = new StringBuffer(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - string = sb.toString().trim(); - if ("".equals(string)) { - throw this.syntaxError("Missing value"); - } - return JSONObject.stringToValue(string); - } - - - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. - * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. - */ - public char skipTo(char to) throws JSONException { - char c; - try { - long startIndex = this.index; - long startCharacter = this.character; - long startLine = this.line; - this.reader.mark(1000000); - do { - c = this.next(); - if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; - return c; - } - } while (c != to); - } catch (IOException exc) { - throw new JSONException(exc); - } - - this.back(); - return c; - } - - - /** - * Make a JSONException to signal a syntax error. - * - * @param message The error message. - * @return A JSONException object, suitable for throwing - */ - public JSONException syntaxError(String message) { - return new JSONException(message + this.toString()); - } - - - /** - * Make a printable string of this JSONTokener. - * - * @return " at {index} [character {character} line {line}]" - */ - public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; - } -} diff --git a/dot/org/json/JSONWriter.java b/dot/org/json/JSONWriter.java deleted file mode 100755 index 855b2bd..0000000 --- a/dot/org/json/JSONWriter.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.json; - -import java.io.IOException; -import java.io.Writer; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * JSONWriter provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONWriter can produce one JSON text. - *

    - * A JSONWriter instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting a cascade style. For example,

    - * new JSONWriter(myWriter)
    - *     .object()
    - *         .key("JSON")
    - *         .value("Hello, World!")
    - *     .endObject();
    which writes
    - * {"JSON":"Hello, World!"}
    - *

    - * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

    - * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONWriter { - private static final int maxdepth = 200; - - /** - * The comma flag determines if a comma should be output before the next - * value. - */ - private boolean comma; - - /** - * The current mode. Values: - * 'a' (array), - * 'd' (done), - * 'i' (initial), - * 'k' (key), - * 'o' (object). - */ - protected char mode; - - /** - * The object/array stack. - */ - private final JSONObject stack[]; - - /** - * The stack top index. A value of 0 indicates that the stack is empty. - */ - private int top; - - /** - * The writer that will receive the output. - */ - protected Writer writer; - - /** - * Make a fresh JSONWriter. It can be used to build one JSON text. - */ - public JSONWriter(Writer w) { - this.comma = false; - this.mode = 'i'; - this.stack = new JSONObject[maxdepth]; - this.top = 0; - this.writer = w; - } - - /** - * Append a value. - * @param string A string value. - * @return this - * @throws JSONException If the value is out of sequence. - */ - private JSONWriter append(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null pointer"); - } - if (this.mode == 'o' || this.mode == 'a') { - try { - if (this.comma && this.mode == 'a') { - this.writer.write(','); - } - this.writer.write(string); - } catch (IOException e) { - throw new JSONException(e); - } - if (this.mode == 'o') { - this.mode = 'k'; - } - this.comma = true; - return this; - } - throw new JSONException("Value out of sequence."); - } - - /** - * Begin appending a new array. All values until the balancing - * endArray will be appended to this array. The - * endArray method must be called to mark the array's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter array() throws JSONException { - if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { - this.push(null); - this.append("["); - this.comma = false; - return this; - } - throw new JSONException("Misplaced array."); - } - - /** - * End something. - * @param mode Mode - * @param c Closing character - * @return this - * @throws JSONException If unbalanced. - */ - private JSONWriter end(char mode, char c) throws JSONException { - if (this.mode != mode) { - throw new JSONException(mode == 'a' - ? "Misplaced endArray." - : "Misplaced endObject."); - } - this.pop(mode); - try { - this.writer.write(c); - } catch (IOException e) { - throw new JSONException(e); - } - this.comma = true; - return this; - } - - /** - * End an array. This method most be called to balance calls to - * array. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endArray() throws JSONException { - return this.end('a', ']'); - } - - /** - * End an object. This method most be called to balance calls to - * object. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endObject() throws JSONException { - return this.end('k', '}'); - } - - /** - * Append a key. The key will be associated with the next value. In an - * object, every value must be preceded by a key. - * @param string A key string. - * @return this - * @throws JSONException If the key is out of place. For example, keys - * do not belong in arrays or if the key is null. - */ - public JSONWriter key(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null key."); - } - if (this.mode == 'k') { - try { - this.stack[this.top - 1].putOnce(string, Boolean.TRUE); - if (this.comma) { - this.writer.write(','); - } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); - this.comma = false; - this.mode = 'o'; - return this; - } catch (IOException e) { - throw new JSONException(e); - } - } - throw new JSONException("Misplaced key."); - } - - - /** - * Begin appending a new object. All keys and values until the balancing - * endObject will be appended to this object. The - * endObject method must be called to mark the object's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter object() throws JSONException { - if (this.mode == 'i') { - this.mode = 'o'; - } - if (this.mode == 'o' || this.mode == 'a') { - this.append("{"); - this.push(new JSONObject()); - this.comma = false; - return this; - } - throw new JSONException("Misplaced object."); - - } - - - /** - * Pop an array or object scope. - * @param c The scope to close. - * @throws JSONException If nesting is wrong. - */ - private void pop(char c) throws JSONException { - if (this.top <= 0) { - throw new JSONException("Nesting error."); - } - char m = this.stack[this.top - 1] == null ? 'a' : 'k'; - if (m != c) { - throw new JSONException("Nesting error."); - } - this.top -= 1; - this.mode = this.top == 0 - ? 'd' - : this.stack[this.top - 1] == null - ? 'a' - : 'k'; - } - - /** - * Push an array or object scope. - * @param c The scope to open. - * @throws JSONException If nesting is too deep. - */ - private void push(JSONObject jo) throws JSONException { - if (this.top >= maxdepth) { - throw new JSONException("Nesting too deep."); - } - this.stack[this.top] = jo; - this.mode = jo == null ? 'a' : 'k'; - this.top += 1; - } - - - /** - * Append either the value true or the value - * false. - * @param b A boolean. - * @return this - * @throws JSONException - */ - public JSONWriter value(boolean b) throws JSONException { - return this.append(b ? "true" : "false"); - } - - /** - * Append a double value. - * @param d A double. - * @return this - * @throws JSONException If the number is not finite. - */ - public JSONWriter value(double d) throws JSONException { - return this.value(new Double(d)); - } - - /** - * Append a long value. - * @param l A long. - * @return this - * @throws JSONException - */ - public JSONWriter value(long l) throws JSONException { - return this.append(Long.toString(l)); - } - - - /** - * Append an object value. - * @param object The object to append. It can be null, or a Boolean, Number, - * String, JSONObject, or JSONArray, or an object that implements JSONString. - * @return this - * @throws JSONException If the value is out of sequence. - */ - public JSONWriter value(Object object) throws JSONException { - return this.append(JSONObject.valueToString(object)); - } -} diff --git a/dot/org/json/XML.java b/dot/org/json/XML.java deleted file mode 100755 index 82455b3..0000000 --- a/dot/org/json/XML.java +++ /dev/null @@ -1,508 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONObject, - * and to covert a JSONObject into an XML text. - * @author JSON.org - * @version 2011-02-11 - */ -public class XML { - - /** The Character '&'. */ - public static final Character AMP = new Character('&'); - - /** The Character '''. */ - public static final Character APOS = new Character('\''); - - /** The Character '!'. */ - public static final Character BANG = new Character('!'); - - /** The Character '='. */ - public static final Character EQ = new Character('='); - - /** The Character '>'. */ - public static final Character GT = new Character('>'); - - /** The Character '<'. */ - public static final Character LT = new Character('<'); - - /** The Character '?'. */ - public static final Character QUEST = new Character('?'); - - /** The Character '"'. */ - public static final Character QUOT = new Character('"'); - - /** The Character '/'. */ - public static final Character SLASH = new Character('/'); - - /** - * Replace special characters with XML escapes: - *

    -     * & (ampersand) is replaced by &amp;
    -     * < (less than) is replaced by &lt;
    -     * > (greater than) is replaced by &gt;
    -     * " (double quote) is replaced by &quot;
    -     * 
    - * @param string The string to be escaped. - * @return The escaped string. - */ - public static String escape(String string) { - StringBuffer sb = new StringBuffer(); - for (int i = 0, length = string.length(); i < length; i++) { - char c = string.charAt(i); - switch (c) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - default: - sb.append(c); - } - } - return sb.toString(); - } - - /** - * Throw an exception if the string contains whitespace. - * Whitespace is not allowed in tagNames and attributes. - * @param string - * @throws JSONException - */ - public static void noSpace(String string) throws JSONException { - int i, length = string.length(); - if (length == 0) { - throw new JSONException("Empty string."); - } - for (i = 0; i < length; i += 1) { - if (Character.isWhitespace(string.charAt(i))) { - throw new JSONException("'" + string + - "' contains a space character."); - } - } - } - - /** - * Scan the content following the named tag, attaching it to the context. - * @param x The XMLTokener containing the source string. - * @param context The JSONObject that will include the new material. - * @param name The tag name. - * @return true if the close tag is processed. - * @throws JSONException - */ - private static boolean parse(XMLTokener x, JSONObject context, - String name) throws JSONException { - char c; - int i; - JSONObject jsonobject = null; - String string; - String tagName; - Object token; - -// Test for and skip past these forms: -// -// -// -// -// Report errors for these forms: -// <> -// <= -// << - - token = x.nextToken(); - -// "); - return false; - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if ("CDATA".equals(token)) { - if (x.next() == '[') { - string = x.nextCDATA(); - if (string.length() > 0) { - context.accumulate("content", string); - } - return false; - } - } - throw x.syntaxError("Expected 'CDATA['"); - } - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - return false; - } else if (token == QUEST) { - -// "); - return false; - } else if (token == SLASH) { - -// Close tag - - } else if (token == SLASH) { - if (x.nextToken() != GT) { - throw x.syntaxError("Misshaped tag"); - } - if (jsonobject.length() > 0) { - context.accumulate(tagName, jsonobject); - } else { - context.accumulate(tagName, ""); - } - return false; - -// Content, between <...> and - - } else if (token == GT) { - for (;;) { - token = x.nextContent(); - if (token == null) { - if (tagName != null) { - throw x.syntaxError("Unclosed tag " + tagName); - } - return false; - } else if (token instanceof String) { - string = (String)token; - if (string.length() > 0) { - jsonobject.accumulate("content", - XML.stringToValue(string)); - } - -// Nested element - - } else if (token == LT) { - if (parse(x, jsonobject, tagName)) { - if (jsonobject.length() == 0) { - context.accumulate(tagName, ""); - } else if (jsonobject.length() == 1 && - jsonobject.opt("content") != null) { - context.accumulate(tagName, - jsonobject.opt("content")); - } else { - context.accumulate(tagName, jsonobject); - } - return false; - } - } - } - } else { - throw x.syntaxError("Misshaped tag"); - } - } - } - } - - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. This is much less ambitious than - * JSONObject.stringToValue, especially because it does not attempt to - * convert plus forms, octal forms, hex forms, or E forms lacking decimal - * points. - * @param string A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - if ("".equals(string)) { - return string; - } - if ("true".equalsIgnoreCase(string)) { - return Boolean.TRUE; - } - if ("false".equalsIgnoreCase(string)) { - return Boolean.FALSE; - } - if ("null".equalsIgnoreCase(string)) { - return JSONObject.NULL; - } - if ("0".equals(string)) { - return new Integer(0); - } - -// If it might be a number, try converting it. If that doesn't work, -// return the string. - - try { - char initial = string.charAt(0); - boolean negative = false; - if (initial == '-') { - initial = string.charAt(1); - negative = true; - } - if (initial == '0' && string.charAt(negative ? 2 : 1) == '0') { - return string; - } - if ((initial >= '0' && initial <= '9')) { - if (string.indexOf('.') >= 0) { - return Double.valueOf(string); - } else if (string.indexOf('e') < 0 && string.indexOf('E') < 0) { - Long myLong = new Long(string); - if (myLong.longValue() == myLong.intValue()) { - return new Integer(myLong.intValue()); - } else { - return myLong; - } - } - } - } catch (Exception ignore) { - } - return string; - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject. Some information may be lost in this transformation - * because JSON is a data format and XML is a document format. XML uses - * elements, attributes, and content text, while JSON uses unordered - * collections of name/value pairs and arrays of values. JSON does not - * does not like to distinguish between elements and attributes. - * Sequences of similar elements are represented as JSONArrays. Content - * text may be placed in a "content" member. Comments, prologs, DTDs, and - * <[ [ ]]> are ignored. - * @param string The source string. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - XMLTokener x = new XMLTokener(string); - while (x.more() && x.skipPast("<")) { - parse(x, jo, null); - } - return jo; - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object) throws JSONException { - return toString(object, null); - } - - - /** - * Convert a JSONObject into a well-formed, element-normal XML string. - * @param object A JSONObject. - * @param tagName The optional name of the enclosing tag. - * @return A string. - * @throws JSONException - */ - public static String toString(Object object, String tagName) - throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - JSONObject jo; - String key; - Iterator keys; - int length; - String string; - Object value; - if (object instanceof JSONObject) { - -// Emit - - if (tagName != null) { - sb.append('<'); - sb.append(tagName); - sb.append('>'); - } - -// Loop thru the keys. - - jo = (JSONObject)object; - keys = jo.keys(); - while (keys.hasNext()) { - key = keys.next().toString(); - value = jo.opt(key); - if (value == null) { - value = ""; - } - if (value instanceof String) { - string = (String)value; - } else { - string = null; - } - -// Emit content in body - - if ("content".equals(key)) { - if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - if (i > 0) { - sb.append('\n'); - } - sb.append(escape(ja.get(i).toString())); - } - } else { - sb.append(escape(value.toString())); - } - -// Emit an array of similar keys - - } else if (value instanceof JSONArray) { - ja = (JSONArray)value; - length = ja.length(); - for (i = 0; i < length; i += 1) { - value = ja.get(i); - if (value instanceof JSONArray) { - sb.append('<'); - sb.append(key); - sb.append('>'); - sb.append(toString(value)); - sb.append("'); - } else { - sb.append(toString(value, key)); - } - } - } else if ("".equals(value)) { - sb.append('<'); - sb.append(key); - sb.append("/>"); - -// Emit a new tag - - } else { - sb.append(toString(value, key)); - } - } - if (tagName != null) { - -// Emit the close tag - - sb.append("'); - } - return sb.toString(); - -// XML does not have good support for arrays. If an array appears in a place -// where XML is lacking, synthesize an element. - - } else { - if (object.getClass().isArray()) { - object = new JSONArray(object); - } - if (object instanceof JSONArray) { - ja = (JSONArray)object; - length = ja.length(); - for (i = 0; i < length; i += 1) { - sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); - } - return sb.toString(); - } else { - string = (object == null) ? "null" : escape(object.toString()); - return (tagName == null) ? "\"" + string + "\"" : - (string.length() == 0) ? "<" + tagName + "/>" : - "<" + tagName + ">" + string + ""; - } - } - } -} \ No newline at end of file diff --git a/dot/org/json/XMLTokener.java b/dot/org/json/XMLTokener.java deleted file mode 100755 index 07574b0..0000000 --- a/dot/org/json/XMLTokener.java +++ /dev/null @@ -1,365 +0,0 @@ -package org.json; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * The XMLTokener extends the JSONTokener to provide additional methods - * for the parsing of XML texts. - * @author JSON.org - * @version 2010-12-24 - */ -public class XMLTokener extends JSONTokener { - - - /** The table of entity values. It initially contains Character values for - * amp, apos, gt, lt, quot. - */ - public static final java.util.HashMap entity; - - static { - entity = new java.util.HashMap(8); - entity.put("amp", XML.AMP); - entity.put("apos", XML.APOS); - entity.put("gt", XML.GT); - entity.put("lt", XML.LT); - entity.put("quot", XML.QUOT); - } - - /** - * Construct an XMLTokener from a string. - * @param s A source string. - */ - public XMLTokener(String s) { - super(s); - } - - /** - * Get the text in the CDATA block. - * @return The string up to the ]]>. - * @throws JSONException If the ]]> is not found. - */ - public String nextCDATA() throws JSONException { - char c; - int i; - StringBuffer sb = new StringBuffer(); - for (;;) { - c = next(); - if (end()) { - throw syntaxError("Unclosed CDATA"); - } - sb.append(c); - i = sb.length() - 3; - if (i >= 0 && sb.charAt(i) == ']' && - sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { - sb.setLength(i); - return sb.toString(); - } - } - } - - - /** - * Get the next XML outer token, trimming whitespace. There are two kinds - * of tokens: the '<' character which begins a markup tag, and the content - * text between markup tags. - * - * @return A string, or a '<' Character, or null if there is no more - * source text. - * @throws JSONException - */ - public Object nextContent() throws JSONException { - char c; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - if (c == 0) { - return null; - } - if (c == '<') { - return XML.LT; - } - sb = new StringBuffer(); - for (;;) { - if (c == '<' || c == 0) { - back(); - return sb.toString().trim(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - c = next(); - } - } - - - /** - * Return the next entity. These entities are translated to Characters: - * & ' > < ". - * @param ampersand An ampersand character. - * @return A Character or an entity String if the entity is not recognized. - * @throws JSONException If missing ';' in XML entity. - */ - public Object nextEntity(char ampersand) throws JSONException { - StringBuffer sb = new StringBuffer(); - for (;;) { - char c = next(); - if (Character.isLetterOrDigit(c) || c == '#') { - sb.append(Character.toLowerCase(c)); - } else if (c == ';') { - break; - } else { - throw syntaxError("Missing ';' in XML entity: &" + sb); - } - } - String string = sb.toString(); - Object object = entity.get(string); - return object != null ? object : ampersand + string + ";"; - } - - - /** - * Returns the next XML meta token. This is used for skipping over - * and structures. - * @return Syntax characters (< > / = ! ?) are returned as - * Character, and strings and names are returned as Boolean. We don't care - * what the values actually are. - * @throws JSONException If a string is not properly closed or if the XML - * is badly structured. - */ - public Object nextMeta() throws JSONException { - char c; - char q; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped meta tag"); - case '<': - return XML.LT; - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - case '"': - case '\'': - q = c; - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return Boolean.TRUE; - } - } - default: - for (;;) { - c = next(); - if (Character.isWhitespace(c)) { - return Boolean.TRUE; - } - switch (c) { - case 0: - case '<': - case '>': - case '/': - case '=': - case '!': - case '?': - case '"': - case '\'': - back(); - return Boolean.TRUE; - } - } - } - } - - - /** - * Get the next XML Token. These tokens are found inside of angle - * brackets. It may be one of these characters: / > = ! ? or it - * may be a string wrapped in single quotes or double quotes, or it may be a - * name. - * @return a String or a Character. - * @throws JSONException If the XML is not well formed. - */ - public Object nextToken() throws JSONException { - char c; - char q; - StringBuffer sb; - do { - c = next(); - } while (Character.isWhitespace(c)); - switch (c) { - case 0: - throw syntaxError("Misshaped element"); - case '<': - throw syntaxError("Misplaced '<'"); - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - -// Quoted string - - case '"': - case '\'': - q = c; - sb = new StringBuffer(); - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); - } - if (c == q) { - return sb.toString(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - } - default: - -// Name - - sb = new StringBuffer(); - for (;;) { - sb.append(c); - c = next(); - if (Character.isWhitespace(c)) { - return sb.toString(); - } - switch (c) { - case 0: - return sb.toString(); - case '>': - case '/': - case '=': - case '!': - case '?': - case '[': - case ']': - back(); - return sb.toString(); - case '<': - case '"': - case '\'': - throw syntaxError("Bad character in a name"); - } - } - } - } - - - /** - * Skip characters until past the requested string. - * If it is not found, we are left at the end of the source with a result of false. - * @param to A string to skip past. - * @throws JSONException - */ - public boolean skipPast(String to) throws JSONException { - boolean b; - char c; - int i; - int j; - int offset = 0; - int length = to.length(); - char[] circle = new char[length]; - - /* - * First fill the circle buffer with as many characters as are in the - * to string. If we reach an early end, bail. - */ - - for (i = 0; i < length; i += 1) { - c = next(); - if (c == 0) { - return false; - } - circle[i] = c; - } - /* - * We will loop, possibly for all of the remaining characters. - */ - for (;;) { - j = offset; - b = true; - /* - * Compare the circle buffer with the to string. - */ - for (i = 0; i < length; i += 1) { - if (circle[j] != to.charAt(i)) { - b = false; - break; - } - j += 1; - if (j >= length) { - j -= length; - } - } - /* - * If we exit the loop with b intact, then victory is ours. - */ - if (b) { - return true; - } - /* - * Get the next character. If there isn't one, then defeat is ours. - */ - c = next(); - if (c == 0) { - return false; - } - /* - * Shove the character in the circle buffer and advance the - * circle offset. The offset is mod n. - */ - circle[offset] = c; - offset += 1; - if (offset >= length) { - offset -= length; - } - } - } -} From 661b73824dce879426e80bd1fc753b7427407fed Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 11:28:00 -0400 Subject: [PATCH 056/140] Rename wdl -> src --- {wdl => src}/Ast.java | 0 {wdl => src}/AstList.java | 0 {wdl => src}/AstNode.java | 0 {wdl => src}/AstTransform.java | 0 {wdl => src}/AstTransformNodeCreator.java | 0 {wdl => src}/AstTransformSubstitution.java | 0 {wdl => src}/CompositeTask.java | 0 {wdl => src}/CompositeTaskEdge.java | 0 {wdl => src}/CompositeTaskEdgeFactory.java | 0 {wdl => src}/CompositeTaskForLoop.java | 0 {wdl => src}/CompositeTaskGraph.java | 0 {wdl => src}/CompositeTaskNode.java | 0 {wdl => src}/CompositeTaskScope.java | 0 {wdl => src}/CompositeTaskStep.java | 0 {wdl => src}/CompositeTaskStepInput.java | 0 {wdl => src}/CompositeTaskStepOutput.java | 0 {wdl => src}/CompositeTaskSubTask.java | 0 {wdl => src}/CompositeTaskToDotCompiler.java | 0 {wdl => src}/CompositeTaskVariable.java | 0 {wdl => src}/CompositeTaskVertex.java | 0 {wdl => src}/ExpressionParser.java | 0 {wdl => src}/Lexer.java | 0 {wdl => src}/NonTerminal.java | 0 {wdl => src}/ParseTree.java | 0 {wdl => src}/ParseTreeNode.java | 0 {wdl => src}/Parser.java | 0 {wdl => src}/README.md | 0 {wdl => src}/SourceCode.java | 0 {wdl => src}/SyntaxError.java | 0 {wdl => src}/SyntaxErrorFormatter.java | 0 {wdl => src}/Terminal.java | 0 {wdl => src}/TerminalIdentifier.java | 0 {wdl => src}/TerminalMap.java | 0 {wdl => src}/TokenStream.java | 0 {wdl => src}/Utility.java | 0 {wdl => src}/WdlAnsiColorizer.java | 0 {wdl => src}/WdlColorTheme.java | 0 {wdl => src}/WdlHtmlColorizer.java | 0 {wdl => src}/WdlMain.java | 0 {wdl => src}/WdlParser.java | 0 {wdl => src}/WdlSourceCode.java | 0 {wdl => src}/WdlSourceCodeFormatter.java | 0 {wdl => src}/WdlSourceCodeNormalizer.java | 0 {wdl => src}/WdlSyntaxErrorFormatter.java | 0 {wdl => src}/WdlTerminalColorizer.java | 0 {wdl => src}/examples/0.wdl | 0 {wdl => src}/examples/1.wdl | 0 {wdl => src}/examples/2.wdl | 0 {wdl => src}/examples/3.wdl | 0 {wdl => src}/examples/4.wdl | 0 {wdl => src}/examples/5.wdl | 0 {wdl => src}/examples/6.wdl | 0 {wdl => src}/examples/7.wdl | 0 {wdl => src}/examples/CopyNumberQC.wdl | 0 {wdl => src}/examples/MutSig.wdl | 0 {wdl => src}/examples/simple.wdl | 0 {wdl => src}/org/jgrapht/DirectedGraph.java | 0 {wdl => src}/org/jgrapht/EdgeFactory.java | 0 {wdl => src}/org/jgrapht/Graph.java | 0 {wdl => src}/org/jgrapht/GraphHelper.java | 0 {wdl => src}/org/jgrapht/GraphMapping.java | 0 {wdl => src}/org/jgrapht/GraphPath.java | 0 {wdl => src}/org/jgrapht/Graphs.java | 0 {wdl => src}/org/jgrapht/ListenableGraph.java | 0 {wdl => src}/org/jgrapht/UndirectedGraph.java | 0 {wdl => src}/org/jgrapht/VertexFactory.java | 0 {wdl => src}/org/jgrapht/WeightedGraph.java | 0 {wdl => src}/org/jgrapht/alg/AbstractPathElement.java | 0 {wdl => src}/org/jgrapht/alg/AbstractPathElementList.java | 0 {wdl => src}/org/jgrapht/alg/BellmanFordIterator.java | 0 {wdl => src}/org/jgrapht/alg/BellmanFordPathElement.java | 0 {wdl => src}/org/jgrapht/alg/BellmanFordShortestPath.java | 0 {wdl => src}/org/jgrapht/alg/BiconnectivityInspector.java | 0 {wdl => src}/org/jgrapht/alg/BlockCutpointGraph.java | 0 {wdl => src}/org/jgrapht/alg/BronKerboschCliqueFinder.java | 0 {wdl => src}/org/jgrapht/alg/ChromaticNumber.java | 0 {wdl => src}/org/jgrapht/alg/ConnectivityInspector.java | 0 {wdl => src}/org/jgrapht/alg/CycleDetector.java | 0 {wdl => src}/org/jgrapht/alg/DijkstraShortestPath.java | 0 {wdl => src}/org/jgrapht/alg/DirectedNeighborIndex.java | 0 {wdl => src}/org/jgrapht/alg/EdmondsBlossomShrinking.java | 0 {wdl => src}/org/jgrapht/alg/EdmondsKarpMaximumFlow.java | 0 {wdl => src}/org/jgrapht/alg/EulerianCircuit.java | 0 {wdl => src}/org/jgrapht/alg/FloydWarshallShortestPaths.java | 0 {wdl => src}/org/jgrapht/alg/HamiltonianCycle.java | 0 {wdl => src}/org/jgrapht/alg/KShortestPaths.java | 0 {wdl => src}/org/jgrapht/alg/KShortestPathsIterator.java | 0 {wdl => src}/org/jgrapht/alg/KruskalMinimumSpanningTree.java | 0 {wdl => src}/org/jgrapht/alg/NeighborIndex.java | 0 {wdl => src}/org/jgrapht/alg/RankingPathElement.java | 0 {wdl => src}/org/jgrapht/alg/RankingPathElementList.java | 0 {wdl => src}/org/jgrapht/alg/StoerWagnerMinimumCut.java | 0 {wdl => src}/org/jgrapht/alg/StrongConnectivityInspector.java | 0 {wdl => src}/org/jgrapht/alg/TransitiveClosure.java | 0 {wdl => src}/org/jgrapht/alg/VertexCovers.java | 0 {wdl => src}/org/jgrapht/alg/package.html | 0 {wdl => src}/org/jgrapht/alg/util/UnionFind.java | 0 {wdl => src}/org/jgrapht/alg/util/VertexDegreeComparator.java | 0 {wdl => src}/org/jgrapht/alg/util/package.html | 0 {wdl => src}/org/jgrapht/event/ConnectedComponentTraversalEvent.java | 0 {wdl => src}/org/jgrapht/event/EdgeTraversalEvent.java | 0 {wdl => src}/org/jgrapht/event/GraphChangeEvent.java | 0 {wdl => src}/org/jgrapht/event/GraphEdgeChangeEvent.java | 0 {wdl => src}/org/jgrapht/event/GraphListener.java | 0 {wdl => src}/org/jgrapht/event/GraphVertexChangeEvent.java | 0 {wdl => src}/org/jgrapht/event/TraversalListener.java | 0 {wdl => src}/org/jgrapht/event/TraversalListenerAdapter.java | 0 {wdl => src}/org/jgrapht/event/VertexSetListener.java | 0 {wdl => src}/org/jgrapht/event/VertexTraversalEvent.java | 0 {wdl => src}/org/jgrapht/event/package.html | 0 {wdl => src}/org/jgrapht/experimental/GraphReader.java | 0 {wdl => src}/org/jgrapht/experimental/GraphSquare.java | 0 {wdl => src}/org/jgrapht/experimental/GraphTests.java | 0 {wdl => src}/org/jgrapht/experimental/PartiteRandomGraphGenerator.java | 0 {wdl => src}/org/jgrapht/experimental/RandomGraphHelper.java | 0 {wdl => src}/org/jgrapht/experimental/UniformRandomGraphGenerator.java | 0 {wdl => src}/org/jgrapht/experimental/alg/ApproximationAlgorithm.java | 0 {wdl => src}/org/jgrapht/experimental/alg/ExactAlgorithm.java | 0 {wdl => src}/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java | 0 .../org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java | 0 {wdl => src}/org/jgrapht/experimental/alg/color/GreedyColoring.java | 0 {wdl => src}/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java | 0 .../org/jgrapht/experimental/equivalence/EquivalenceComparator.java | 0 .../org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java | 0 .../jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java | 0 {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceSet.java | 0 .../org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java | 0 .../jgrapht/experimental/equivalence/UniformEquivalenceComparator.java | 0 {wdl => src}/org/jgrapht/experimental/equivalence/package.html | 0 .../experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java | 0 .../experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java | 0 .../jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java | 0 .../org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java | 0 {wdl => src}/org/jgrapht/experimental/isomorphism/GraphOrdering.java | 0 .../org/jgrapht/experimental/isomorphism/IsomorphismRelation.java | 0 .../jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java | 0 .../experimental/isomorphism/VertexDegreeEquivalenceComparator.java | 0 {wdl => src}/org/jgrapht/experimental/isomorphism/package.html | 0 {wdl => src}/org/jgrapht/experimental/package.html | 0 .../org/jgrapht/experimental/permutation/ArrayPermutationsIter.java | 0 .../org/jgrapht/experimental/permutation/CollectionPermutationIter.java | 0 .../org/jgrapht/experimental/permutation/CompoundPermutationIter.java | 0 .../org/jgrapht/experimental/permutation/IntegerPermutationIter.java | 0 {wdl => src}/org/jgrapht/experimental/permutation/PermutationFactory.java | 0 {wdl => src}/org/jgrapht/experimental/permutation/package.html | 0 {wdl => src}/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/CompleteGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/EmptyGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/GraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/GridGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/HyperCubeGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/LinearGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/RandomGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/RingGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/ScaleFreeGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/StarGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/WheelGraphGenerator.java | 0 {wdl => src}/org/jgrapht/generate/package.html | 0 {wdl => src}/org/jgrapht/graph/AbstractBaseGraph.java | 0 {wdl => src}/org/jgrapht/graph/AbstractGraph.java | 0 {wdl => src}/org/jgrapht/graph/AsUndirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/AsUnweightedDirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/AsUnweightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/AsWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/ClassBasedEdgeFactory.java | 0 {wdl => src}/org/jgrapht/graph/ClassBasedVertexFactory.java | 0 {wdl => src}/org/jgrapht/graph/DefaultDirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/DefaultDirectedWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/DefaultEdge.java | 0 {wdl => src}/org/jgrapht/graph/DefaultGraphMapping.java | 0 {wdl => src}/org/jgrapht/graph/DefaultListenableGraph.java | 0 {wdl => src}/org/jgrapht/graph/DefaultWeightedEdge.java | 0 {wdl => src}/org/jgrapht/graph/DirectedGraphUnion.java | 0 {wdl => src}/org/jgrapht/graph/DirectedMaskSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/DirectedMultigraph.java | 0 {wdl => src}/org/jgrapht/graph/DirectedPseudograph.java | 0 {wdl => src}/org/jgrapht/graph/DirectedSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/DirectedWeightedMultigraph.java | 0 {wdl => src}/org/jgrapht/graph/DirectedWeightedSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/EdgeReversedGraph.java | 0 {wdl => src}/org/jgrapht/graph/EdgeSetFactory.java | 0 {wdl => src}/org/jgrapht/graph/GraphDelegator.java | 0 {wdl => src}/org/jgrapht/graph/GraphPathImpl.java | 0 {wdl => src}/org/jgrapht/graph/GraphUnion.java | 0 {wdl => src}/org/jgrapht/graph/IntrusiveEdge.java | 0 {wdl => src}/org/jgrapht/graph/ListenableDirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/ListenableDirectedWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/ListenableUndirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/MaskEdgeSet.java | 0 {wdl => src}/org/jgrapht/graph/MaskFunctor.java | 0 {wdl => src}/org/jgrapht/graph/MaskSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/MaskVertexSet.java | 0 {wdl => src}/org/jgrapht/graph/Multigraph.java | 0 {wdl => src}/org/jgrapht/graph/ParanoidGraph.java | 0 {wdl => src}/org/jgrapht/graph/Pseudograph.java | 0 {wdl => src}/org/jgrapht/graph/SimpleDirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/SimpleDirectedWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/SimpleGraph.java | 0 {wdl => src}/org/jgrapht/graph/SimpleWeightedGraph.java | 0 {wdl => src}/org/jgrapht/graph/Subgraph.java | 0 {wdl => src}/org/jgrapht/graph/UndirectedGraphUnion.java | 0 {wdl => src}/org/jgrapht/graph/UndirectedMaskSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/UndirectedSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/UndirectedWeightedSubgraph.java | 0 {wdl => src}/org/jgrapht/graph/UnmodifiableDirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/UnmodifiableGraph.java | 0 {wdl => src}/org/jgrapht/graph/UnmodifiableUndirectedGraph.java | 0 {wdl => src}/org/jgrapht/graph/WeightedMultigraph.java | 0 {wdl => src}/org/jgrapht/graph/WeightedPseudograph.java | 0 {wdl => src}/org/jgrapht/graph/package.html | 0 {wdl => src}/org/jgrapht/package.html | 0 {wdl => src}/org/jgrapht/traverse/AbstractGraphIterator.java | 0 {wdl => src}/org/jgrapht/traverse/BreadthFirstIterator.java | 0 {wdl => src}/org/jgrapht/traverse/ClosestFirstIterator.java | 0 {wdl => src}/org/jgrapht/traverse/CrossComponentIterator.java | 0 {wdl => src}/org/jgrapht/traverse/DepthFirstIterator.java | 0 {wdl => src}/org/jgrapht/traverse/GraphIterator.java | 0 {wdl => src}/org/jgrapht/traverse/TopologicalOrderIterator.java | 0 {wdl => src}/org/jgrapht/traverse/package.html | 0 {wdl => src}/org/jgrapht/util/ArrayUnenforcedSet.java | 0 {wdl => src}/org/jgrapht/util/FibonacciHeap.java | 0 {wdl => src}/org/jgrapht/util/FibonacciHeapNode.java | 0 {wdl => src}/org/jgrapht/util/MathUtil.java | 0 {wdl => src}/org/jgrapht/util/ModifiableInteger.java | 0 {wdl => src}/org/jgrapht/util/PrefetchIterator.java | 0 {wdl => src}/org/jgrapht/util/TypeUtil.java | 0 {wdl => src}/org/jgrapht/util/VertexPair.java | 0 {wdl => src}/org/jgrapht/util/WeightCombiner.java | 0 {wdl => src}/org/jgrapht/util/package.html | 0 {wdl => src}/wdl.zgr | 0 231 files changed, 0 insertions(+), 0 deletions(-) rename {wdl => src}/Ast.java (100%) rename {wdl => src}/AstList.java (100%) rename {wdl => src}/AstNode.java (100%) rename {wdl => src}/AstTransform.java (100%) rename {wdl => src}/AstTransformNodeCreator.java (100%) rename {wdl => src}/AstTransformSubstitution.java (100%) rename {wdl => src}/CompositeTask.java (100%) rename {wdl => src}/CompositeTaskEdge.java (100%) rename {wdl => src}/CompositeTaskEdgeFactory.java (100%) rename {wdl => src}/CompositeTaskForLoop.java (100%) rename {wdl => src}/CompositeTaskGraph.java (100%) rename {wdl => src}/CompositeTaskNode.java (100%) rename {wdl => src}/CompositeTaskScope.java (100%) rename {wdl => src}/CompositeTaskStep.java (100%) rename {wdl => src}/CompositeTaskStepInput.java (100%) rename {wdl => src}/CompositeTaskStepOutput.java (100%) rename {wdl => src}/CompositeTaskSubTask.java (100%) rename {wdl => src}/CompositeTaskToDotCompiler.java (100%) rename {wdl => src}/CompositeTaskVariable.java (100%) rename {wdl => src}/CompositeTaskVertex.java (100%) rename {wdl => src}/ExpressionParser.java (100%) rename {wdl => src}/Lexer.java (100%) rename {wdl => src}/NonTerminal.java (100%) rename {wdl => src}/ParseTree.java (100%) rename {wdl => src}/ParseTreeNode.java (100%) rename {wdl => src}/Parser.java (100%) rename {wdl => src}/README.md (100%) rename {wdl => src}/SourceCode.java (100%) rename {wdl => src}/SyntaxError.java (100%) rename {wdl => src}/SyntaxErrorFormatter.java (100%) rename {wdl => src}/Terminal.java (100%) rename {wdl => src}/TerminalIdentifier.java (100%) rename {wdl => src}/TerminalMap.java (100%) rename {wdl => src}/TokenStream.java (100%) rename {wdl => src}/Utility.java (100%) rename {wdl => src}/WdlAnsiColorizer.java (100%) rename {wdl => src}/WdlColorTheme.java (100%) rename {wdl => src}/WdlHtmlColorizer.java (100%) rename {wdl => src}/WdlMain.java (100%) rename {wdl => src}/WdlParser.java (100%) rename {wdl => src}/WdlSourceCode.java (100%) rename {wdl => src}/WdlSourceCodeFormatter.java (100%) rename {wdl => src}/WdlSourceCodeNormalizer.java (100%) rename {wdl => src}/WdlSyntaxErrorFormatter.java (100%) rename {wdl => src}/WdlTerminalColorizer.java (100%) rename {wdl => src}/examples/0.wdl (100%) rename {wdl => src}/examples/1.wdl (100%) rename {wdl => src}/examples/2.wdl (100%) rename {wdl => src}/examples/3.wdl (100%) rename {wdl => src}/examples/4.wdl (100%) rename {wdl => src}/examples/5.wdl (100%) rename {wdl => src}/examples/6.wdl (100%) rename {wdl => src}/examples/7.wdl (100%) rename {wdl => src}/examples/CopyNumberQC.wdl (100%) rename {wdl => src}/examples/MutSig.wdl (100%) rename {wdl => src}/examples/simple.wdl (100%) rename {wdl => src}/org/jgrapht/DirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/EdgeFactory.java (100%) rename {wdl => src}/org/jgrapht/Graph.java (100%) rename {wdl => src}/org/jgrapht/GraphHelper.java (100%) rename {wdl => src}/org/jgrapht/GraphMapping.java (100%) rename {wdl => src}/org/jgrapht/GraphPath.java (100%) rename {wdl => src}/org/jgrapht/Graphs.java (100%) rename {wdl => src}/org/jgrapht/ListenableGraph.java (100%) rename {wdl => src}/org/jgrapht/UndirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/VertexFactory.java (100%) rename {wdl => src}/org/jgrapht/WeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/alg/AbstractPathElement.java (100%) rename {wdl => src}/org/jgrapht/alg/AbstractPathElementList.java (100%) rename {wdl => src}/org/jgrapht/alg/BellmanFordIterator.java (100%) rename {wdl => src}/org/jgrapht/alg/BellmanFordPathElement.java (100%) rename {wdl => src}/org/jgrapht/alg/BellmanFordShortestPath.java (100%) rename {wdl => src}/org/jgrapht/alg/BiconnectivityInspector.java (100%) rename {wdl => src}/org/jgrapht/alg/BlockCutpointGraph.java (100%) rename {wdl => src}/org/jgrapht/alg/BronKerboschCliqueFinder.java (100%) rename {wdl => src}/org/jgrapht/alg/ChromaticNumber.java (100%) rename {wdl => src}/org/jgrapht/alg/ConnectivityInspector.java (100%) rename {wdl => src}/org/jgrapht/alg/CycleDetector.java (100%) rename {wdl => src}/org/jgrapht/alg/DijkstraShortestPath.java (100%) rename {wdl => src}/org/jgrapht/alg/DirectedNeighborIndex.java (100%) rename {wdl => src}/org/jgrapht/alg/EdmondsBlossomShrinking.java (100%) rename {wdl => src}/org/jgrapht/alg/EdmondsKarpMaximumFlow.java (100%) rename {wdl => src}/org/jgrapht/alg/EulerianCircuit.java (100%) rename {wdl => src}/org/jgrapht/alg/FloydWarshallShortestPaths.java (100%) rename {wdl => src}/org/jgrapht/alg/HamiltonianCycle.java (100%) rename {wdl => src}/org/jgrapht/alg/KShortestPaths.java (100%) rename {wdl => src}/org/jgrapht/alg/KShortestPathsIterator.java (100%) rename {wdl => src}/org/jgrapht/alg/KruskalMinimumSpanningTree.java (100%) rename {wdl => src}/org/jgrapht/alg/NeighborIndex.java (100%) rename {wdl => src}/org/jgrapht/alg/RankingPathElement.java (100%) rename {wdl => src}/org/jgrapht/alg/RankingPathElementList.java (100%) rename {wdl => src}/org/jgrapht/alg/StoerWagnerMinimumCut.java (100%) rename {wdl => src}/org/jgrapht/alg/StrongConnectivityInspector.java (100%) rename {wdl => src}/org/jgrapht/alg/TransitiveClosure.java (100%) rename {wdl => src}/org/jgrapht/alg/VertexCovers.java (100%) rename {wdl => src}/org/jgrapht/alg/package.html (100%) rename {wdl => src}/org/jgrapht/alg/util/UnionFind.java (100%) rename {wdl => src}/org/jgrapht/alg/util/VertexDegreeComparator.java (100%) rename {wdl => src}/org/jgrapht/alg/util/package.html (100%) rename {wdl => src}/org/jgrapht/event/ConnectedComponentTraversalEvent.java (100%) rename {wdl => src}/org/jgrapht/event/EdgeTraversalEvent.java (100%) rename {wdl => src}/org/jgrapht/event/GraphChangeEvent.java (100%) rename {wdl => src}/org/jgrapht/event/GraphEdgeChangeEvent.java (100%) rename {wdl => src}/org/jgrapht/event/GraphListener.java (100%) rename {wdl => src}/org/jgrapht/event/GraphVertexChangeEvent.java (100%) rename {wdl => src}/org/jgrapht/event/TraversalListener.java (100%) rename {wdl => src}/org/jgrapht/event/TraversalListenerAdapter.java (100%) rename {wdl => src}/org/jgrapht/event/VertexSetListener.java (100%) rename {wdl => src}/org/jgrapht/event/VertexTraversalEvent.java (100%) rename {wdl => src}/org/jgrapht/event/package.html (100%) rename {wdl => src}/org/jgrapht/experimental/GraphReader.java (100%) rename {wdl => src}/org/jgrapht/experimental/GraphSquare.java (100%) rename {wdl => src}/org/jgrapht/experimental/GraphTests.java (100%) rename {wdl => src}/org/jgrapht/experimental/PartiteRandomGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/experimental/RandomGraphHelper.java (100%) rename {wdl => src}/org/jgrapht/experimental/UniformRandomGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/experimental/alg/ApproximationAlgorithm.java (100%) rename {wdl => src}/org/jgrapht/experimental/alg/ExactAlgorithm.java (100%) rename {wdl => src}/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java (100%) rename {wdl => src}/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java (100%) rename {wdl => src}/org/jgrapht/experimental/alg/color/GreedyColoring.java (100%) rename {wdl => src}/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceComparator.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceSet.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java (100%) rename {wdl => src}/org/jgrapht/experimental/equivalence/package.html (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/GraphOrdering.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java (100%) rename {wdl => src}/org/jgrapht/experimental/isomorphism/package.html (100%) rename {wdl => src}/org/jgrapht/experimental/package.html (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/CollectionPermutationIter.java (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/CompoundPermutationIter.java (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/IntegerPermutationIter.java (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/PermutationFactory.java (100%) rename {wdl => src}/org/jgrapht/experimental/permutation/package.html (100%) rename {wdl => src}/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/CompleteGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/EmptyGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/GraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/GridGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/HyperCubeGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/LinearGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/RandomGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/RingGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/ScaleFreeGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/StarGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/WheelGraphGenerator.java (100%) rename {wdl => src}/org/jgrapht/generate/package.html (100%) rename {wdl => src}/org/jgrapht/graph/AbstractBaseGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/AbstractGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/AsUndirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/AsUnweightedDirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/AsUnweightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/AsWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/ClassBasedEdgeFactory.java (100%) rename {wdl => src}/org/jgrapht/graph/ClassBasedVertexFactory.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultDirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultDirectedWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultEdge.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultGraphMapping.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultListenableGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DefaultWeightedEdge.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedGraphUnion.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedMaskSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedMultigraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedPseudograph.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedWeightedMultigraph.java (100%) rename {wdl => src}/org/jgrapht/graph/DirectedWeightedSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/EdgeReversedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/EdgeSetFactory.java (100%) rename {wdl => src}/org/jgrapht/graph/GraphDelegator.java (100%) rename {wdl => src}/org/jgrapht/graph/GraphPathImpl.java (100%) rename {wdl => src}/org/jgrapht/graph/GraphUnion.java (100%) rename {wdl => src}/org/jgrapht/graph/IntrusiveEdge.java (100%) rename {wdl => src}/org/jgrapht/graph/ListenableDirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/ListenableDirectedWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/ListenableUndirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/MaskEdgeSet.java (100%) rename {wdl => src}/org/jgrapht/graph/MaskFunctor.java (100%) rename {wdl => src}/org/jgrapht/graph/MaskSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/MaskVertexSet.java (100%) rename {wdl => src}/org/jgrapht/graph/Multigraph.java (100%) rename {wdl => src}/org/jgrapht/graph/ParanoidGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/Pseudograph.java (100%) rename {wdl => src}/org/jgrapht/graph/SimpleDirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/SimpleDirectedWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/SimpleGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/SimpleWeightedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/Subgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UndirectedGraphUnion.java (100%) rename {wdl => src}/org/jgrapht/graph/UndirectedMaskSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UndirectedSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UndirectedWeightedSubgraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UnmodifiableDirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UnmodifiableGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/UnmodifiableUndirectedGraph.java (100%) rename {wdl => src}/org/jgrapht/graph/WeightedMultigraph.java (100%) rename {wdl => src}/org/jgrapht/graph/WeightedPseudograph.java (100%) rename {wdl => src}/org/jgrapht/graph/package.html (100%) rename {wdl => src}/org/jgrapht/package.html (100%) rename {wdl => src}/org/jgrapht/traverse/AbstractGraphIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/BreadthFirstIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/ClosestFirstIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/CrossComponentIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/DepthFirstIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/GraphIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/TopologicalOrderIterator.java (100%) rename {wdl => src}/org/jgrapht/traverse/package.html (100%) rename {wdl => src}/org/jgrapht/util/ArrayUnenforcedSet.java (100%) rename {wdl => src}/org/jgrapht/util/FibonacciHeap.java (100%) rename {wdl => src}/org/jgrapht/util/FibonacciHeapNode.java (100%) rename {wdl => src}/org/jgrapht/util/MathUtil.java (100%) rename {wdl => src}/org/jgrapht/util/ModifiableInteger.java (100%) rename {wdl => src}/org/jgrapht/util/PrefetchIterator.java (100%) rename {wdl => src}/org/jgrapht/util/TypeUtil.java (100%) rename {wdl => src}/org/jgrapht/util/VertexPair.java (100%) rename {wdl => src}/org/jgrapht/util/WeightCombiner.java (100%) rename {wdl => src}/org/jgrapht/util/package.html (100%) rename {wdl => src}/wdl.zgr (100%) diff --git a/wdl/Ast.java b/src/Ast.java similarity index 100% rename from wdl/Ast.java rename to src/Ast.java diff --git a/wdl/AstList.java b/src/AstList.java similarity index 100% rename from wdl/AstList.java rename to src/AstList.java diff --git a/wdl/AstNode.java b/src/AstNode.java similarity index 100% rename from wdl/AstNode.java rename to src/AstNode.java diff --git a/wdl/AstTransform.java b/src/AstTransform.java similarity index 100% rename from wdl/AstTransform.java rename to src/AstTransform.java diff --git a/wdl/AstTransformNodeCreator.java b/src/AstTransformNodeCreator.java similarity index 100% rename from wdl/AstTransformNodeCreator.java rename to src/AstTransformNodeCreator.java diff --git a/wdl/AstTransformSubstitution.java b/src/AstTransformSubstitution.java similarity index 100% rename from wdl/AstTransformSubstitution.java rename to src/AstTransformSubstitution.java diff --git a/wdl/CompositeTask.java b/src/CompositeTask.java similarity index 100% rename from wdl/CompositeTask.java rename to src/CompositeTask.java diff --git a/wdl/CompositeTaskEdge.java b/src/CompositeTaskEdge.java similarity index 100% rename from wdl/CompositeTaskEdge.java rename to src/CompositeTaskEdge.java diff --git a/wdl/CompositeTaskEdgeFactory.java b/src/CompositeTaskEdgeFactory.java similarity index 100% rename from wdl/CompositeTaskEdgeFactory.java rename to src/CompositeTaskEdgeFactory.java diff --git a/wdl/CompositeTaskForLoop.java b/src/CompositeTaskForLoop.java similarity index 100% rename from wdl/CompositeTaskForLoop.java rename to src/CompositeTaskForLoop.java diff --git a/wdl/CompositeTaskGraph.java b/src/CompositeTaskGraph.java similarity index 100% rename from wdl/CompositeTaskGraph.java rename to src/CompositeTaskGraph.java diff --git a/wdl/CompositeTaskNode.java b/src/CompositeTaskNode.java similarity index 100% rename from wdl/CompositeTaskNode.java rename to src/CompositeTaskNode.java diff --git a/wdl/CompositeTaskScope.java b/src/CompositeTaskScope.java similarity index 100% rename from wdl/CompositeTaskScope.java rename to src/CompositeTaskScope.java diff --git a/wdl/CompositeTaskStep.java b/src/CompositeTaskStep.java similarity index 100% rename from wdl/CompositeTaskStep.java rename to src/CompositeTaskStep.java diff --git a/wdl/CompositeTaskStepInput.java b/src/CompositeTaskStepInput.java similarity index 100% rename from wdl/CompositeTaskStepInput.java rename to src/CompositeTaskStepInput.java diff --git a/wdl/CompositeTaskStepOutput.java b/src/CompositeTaskStepOutput.java similarity index 100% rename from wdl/CompositeTaskStepOutput.java rename to src/CompositeTaskStepOutput.java diff --git a/wdl/CompositeTaskSubTask.java b/src/CompositeTaskSubTask.java similarity index 100% rename from wdl/CompositeTaskSubTask.java rename to src/CompositeTaskSubTask.java diff --git a/wdl/CompositeTaskToDotCompiler.java b/src/CompositeTaskToDotCompiler.java similarity index 100% rename from wdl/CompositeTaskToDotCompiler.java rename to src/CompositeTaskToDotCompiler.java diff --git a/wdl/CompositeTaskVariable.java b/src/CompositeTaskVariable.java similarity index 100% rename from wdl/CompositeTaskVariable.java rename to src/CompositeTaskVariable.java diff --git a/wdl/CompositeTaskVertex.java b/src/CompositeTaskVertex.java similarity index 100% rename from wdl/CompositeTaskVertex.java rename to src/CompositeTaskVertex.java diff --git a/wdl/ExpressionParser.java b/src/ExpressionParser.java similarity index 100% rename from wdl/ExpressionParser.java rename to src/ExpressionParser.java diff --git a/wdl/Lexer.java b/src/Lexer.java similarity index 100% rename from wdl/Lexer.java rename to src/Lexer.java diff --git a/wdl/NonTerminal.java b/src/NonTerminal.java similarity index 100% rename from wdl/NonTerminal.java rename to src/NonTerminal.java diff --git a/wdl/ParseTree.java b/src/ParseTree.java similarity index 100% rename from wdl/ParseTree.java rename to src/ParseTree.java diff --git a/wdl/ParseTreeNode.java b/src/ParseTreeNode.java similarity index 100% rename from wdl/ParseTreeNode.java rename to src/ParseTreeNode.java diff --git a/wdl/Parser.java b/src/Parser.java similarity index 100% rename from wdl/Parser.java rename to src/Parser.java diff --git a/wdl/README.md b/src/README.md similarity index 100% rename from wdl/README.md rename to src/README.md diff --git a/wdl/SourceCode.java b/src/SourceCode.java similarity index 100% rename from wdl/SourceCode.java rename to src/SourceCode.java diff --git a/wdl/SyntaxError.java b/src/SyntaxError.java similarity index 100% rename from wdl/SyntaxError.java rename to src/SyntaxError.java diff --git a/wdl/SyntaxErrorFormatter.java b/src/SyntaxErrorFormatter.java similarity index 100% rename from wdl/SyntaxErrorFormatter.java rename to src/SyntaxErrorFormatter.java diff --git a/wdl/Terminal.java b/src/Terminal.java similarity index 100% rename from wdl/Terminal.java rename to src/Terminal.java diff --git a/wdl/TerminalIdentifier.java b/src/TerminalIdentifier.java similarity index 100% rename from wdl/TerminalIdentifier.java rename to src/TerminalIdentifier.java diff --git a/wdl/TerminalMap.java b/src/TerminalMap.java similarity index 100% rename from wdl/TerminalMap.java rename to src/TerminalMap.java diff --git a/wdl/TokenStream.java b/src/TokenStream.java similarity index 100% rename from wdl/TokenStream.java rename to src/TokenStream.java diff --git a/wdl/Utility.java b/src/Utility.java similarity index 100% rename from wdl/Utility.java rename to src/Utility.java diff --git a/wdl/WdlAnsiColorizer.java b/src/WdlAnsiColorizer.java similarity index 100% rename from wdl/WdlAnsiColorizer.java rename to src/WdlAnsiColorizer.java diff --git a/wdl/WdlColorTheme.java b/src/WdlColorTheme.java similarity index 100% rename from wdl/WdlColorTheme.java rename to src/WdlColorTheme.java diff --git a/wdl/WdlHtmlColorizer.java b/src/WdlHtmlColorizer.java similarity index 100% rename from wdl/WdlHtmlColorizer.java rename to src/WdlHtmlColorizer.java diff --git a/wdl/WdlMain.java b/src/WdlMain.java similarity index 100% rename from wdl/WdlMain.java rename to src/WdlMain.java diff --git a/wdl/WdlParser.java b/src/WdlParser.java similarity index 100% rename from wdl/WdlParser.java rename to src/WdlParser.java diff --git a/wdl/WdlSourceCode.java b/src/WdlSourceCode.java similarity index 100% rename from wdl/WdlSourceCode.java rename to src/WdlSourceCode.java diff --git a/wdl/WdlSourceCodeFormatter.java b/src/WdlSourceCodeFormatter.java similarity index 100% rename from wdl/WdlSourceCodeFormatter.java rename to src/WdlSourceCodeFormatter.java diff --git a/wdl/WdlSourceCodeNormalizer.java b/src/WdlSourceCodeNormalizer.java similarity index 100% rename from wdl/WdlSourceCodeNormalizer.java rename to src/WdlSourceCodeNormalizer.java diff --git a/wdl/WdlSyntaxErrorFormatter.java b/src/WdlSyntaxErrorFormatter.java similarity index 100% rename from wdl/WdlSyntaxErrorFormatter.java rename to src/WdlSyntaxErrorFormatter.java diff --git a/wdl/WdlTerminalColorizer.java b/src/WdlTerminalColorizer.java similarity index 100% rename from wdl/WdlTerminalColorizer.java rename to src/WdlTerminalColorizer.java diff --git a/wdl/examples/0.wdl b/src/examples/0.wdl similarity index 100% rename from wdl/examples/0.wdl rename to src/examples/0.wdl diff --git a/wdl/examples/1.wdl b/src/examples/1.wdl similarity index 100% rename from wdl/examples/1.wdl rename to src/examples/1.wdl diff --git a/wdl/examples/2.wdl b/src/examples/2.wdl similarity index 100% rename from wdl/examples/2.wdl rename to src/examples/2.wdl diff --git a/wdl/examples/3.wdl b/src/examples/3.wdl similarity index 100% rename from wdl/examples/3.wdl rename to src/examples/3.wdl diff --git a/wdl/examples/4.wdl b/src/examples/4.wdl similarity index 100% rename from wdl/examples/4.wdl rename to src/examples/4.wdl diff --git a/wdl/examples/5.wdl b/src/examples/5.wdl similarity index 100% rename from wdl/examples/5.wdl rename to src/examples/5.wdl diff --git a/wdl/examples/6.wdl b/src/examples/6.wdl similarity index 100% rename from wdl/examples/6.wdl rename to src/examples/6.wdl diff --git a/wdl/examples/7.wdl b/src/examples/7.wdl similarity index 100% rename from wdl/examples/7.wdl rename to src/examples/7.wdl diff --git a/wdl/examples/CopyNumberQC.wdl b/src/examples/CopyNumberQC.wdl similarity index 100% rename from wdl/examples/CopyNumberQC.wdl rename to src/examples/CopyNumberQC.wdl diff --git a/wdl/examples/MutSig.wdl b/src/examples/MutSig.wdl similarity index 100% rename from wdl/examples/MutSig.wdl rename to src/examples/MutSig.wdl diff --git a/wdl/examples/simple.wdl b/src/examples/simple.wdl similarity index 100% rename from wdl/examples/simple.wdl rename to src/examples/simple.wdl diff --git a/wdl/org/jgrapht/DirectedGraph.java b/src/org/jgrapht/DirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/DirectedGraph.java rename to src/org/jgrapht/DirectedGraph.java diff --git a/wdl/org/jgrapht/EdgeFactory.java b/src/org/jgrapht/EdgeFactory.java similarity index 100% rename from wdl/org/jgrapht/EdgeFactory.java rename to src/org/jgrapht/EdgeFactory.java diff --git a/wdl/org/jgrapht/Graph.java b/src/org/jgrapht/Graph.java similarity index 100% rename from wdl/org/jgrapht/Graph.java rename to src/org/jgrapht/Graph.java diff --git a/wdl/org/jgrapht/GraphHelper.java b/src/org/jgrapht/GraphHelper.java similarity index 100% rename from wdl/org/jgrapht/GraphHelper.java rename to src/org/jgrapht/GraphHelper.java diff --git a/wdl/org/jgrapht/GraphMapping.java b/src/org/jgrapht/GraphMapping.java similarity index 100% rename from wdl/org/jgrapht/GraphMapping.java rename to src/org/jgrapht/GraphMapping.java diff --git a/wdl/org/jgrapht/GraphPath.java b/src/org/jgrapht/GraphPath.java similarity index 100% rename from wdl/org/jgrapht/GraphPath.java rename to src/org/jgrapht/GraphPath.java diff --git a/wdl/org/jgrapht/Graphs.java b/src/org/jgrapht/Graphs.java similarity index 100% rename from wdl/org/jgrapht/Graphs.java rename to src/org/jgrapht/Graphs.java diff --git a/wdl/org/jgrapht/ListenableGraph.java b/src/org/jgrapht/ListenableGraph.java similarity index 100% rename from wdl/org/jgrapht/ListenableGraph.java rename to src/org/jgrapht/ListenableGraph.java diff --git a/wdl/org/jgrapht/UndirectedGraph.java b/src/org/jgrapht/UndirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/UndirectedGraph.java rename to src/org/jgrapht/UndirectedGraph.java diff --git a/wdl/org/jgrapht/VertexFactory.java b/src/org/jgrapht/VertexFactory.java similarity index 100% rename from wdl/org/jgrapht/VertexFactory.java rename to src/org/jgrapht/VertexFactory.java diff --git a/wdl/org/jgrapht/WeightedGraph.java b/src/org/jgrapht/WeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/WeightedGraph.java rename to src/org/jgrapht/WeightedGraph.java diff --git a/wdl/org/jgrapht/alg/AbstractPathElement.java b/src/org/jgrapht/alg/AbstractPathElement.java similarity index 100% rename from wdl/org/jgrapht/alg/AbstractPathElement.java rename to src/org/jgrapht/alg/AbstractPathElement.java diff --git a/wdl/org/jgrapht/alg/AbstractPathElementList.java b/src/org/jgrapht/alg/AbstractPathElementList.java similarity index 100% rename from wdl/org/jgrapht/alg/AbstractPathElementList.java rename to src/org/jgrapht/alg/AbstractPathElementList.java diff --git a/wdl/org/jgrapht/alg/BellmanFordIterator.java b/src/org/jgrapht/alg/BellmanFordIterator.java similarity index 100% rename from wdl/org/jgrapht/alg/BellmanFordIterator.java rename to src/org/jgrapht/alg/BellmanFordIterator.java diff --git a/wdl/org/jgrapht/alg/BellmanFordPathElement.java b/src/org/jgrapht/alg/BellmanFordPathElement.java similarity index 100% rename from wdl/org/jgrapht/alg/BellmanFordPathElement.java rename to src/org/jgrapht/alg/BellmanFordPathElement.java diff --git a/wdl/org/jgrapht/alg/BellmanFordShortestPath.java b/src/org/jgrapht/alg/BellmanFordShortestPath.java similarity index 100% rename from wdl/org/jgrapht/alg/BellmanFordShortestPath.java rename to src/org/jgrapht/alg/BellmanFordShortestPath.java diff --git a/wdl/org/jgrapht/alg/BiconnectivityInspector.java b/src/org/jgrapht/alg/BiconnectivityInspector.java similarity index 100% rename from wdl/org/jgrapht/alg/BiconnectivityInspector.java rename to src/org/jgrapht/alg/BiconnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/BlockCutpointGraph.java b/src/org/jgrapht/alg/BlockCutpointGraph.java similarity index 100% rename from wdl/org/jgrapht/alg/BlockCutpointGraph.java rename to src/org/jgrapht/alg/BlockCutpointGraph.java diff --git a/wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java b/src/org/jgrapht/alg/BronKerboschCliqueFinder.java similarity index 100% rename from wdl/org/jgrapht/alg/BronKerboschCliqueFinder.java rename to src/org/jgrapht/alg/BronKerboschCliqueFinder.java diff --git a/wdl/org/jgrapht/alg/ChromaticNumber.java b/src/org/jgrapht/alg/ChromaticNumber.java similarity index 100% rename from wdl/org/jgrapht/alg/ChromaticNumber.java rename to src/org/jgrapht/alg/ChromaticNumber.java diff --git a/wdl/org/jgrapht/alg/ConnectivityInspector.java b/src/org/jgrapht/alg/ConnectivityInspector.java similarity index 100% rename from wdl/org/jgrapht/alg/ConnectivityInspector.java rename to src/org/jgrapht/alg/ConnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/CycleDetector.java b/src/org/jgrapht/alg/CycleDetector.java similarity index 100% rename from wdl/org/jgrapht/alg/CycleDetector.java rename to src/org/jgrapht/alg/CycleDetector.java diff --git a/wdl/org/jgrapht/alg/DijkstraShortestPath.java b/src/org/jgrapht/alg/DijkstraShortestPath.java similarity index 100% rename from wdl/org/jgrapht/alg/DijkstraShortestPath.java rename to src/org/jgrapht/alg/DijkstraShortestPath.java diff --git a/wdl/org/jgrapht/alg/DirectedNeighborIndex.java b/src/org/jgrapht/alg/DirectedNeighborIndex.java similarity index 100% rename from wdl/org/jgrapht/alg/DirectedNeighborIndex.java rename to src/org/jgrapht/alg/DirectedNeighborIndex.java diff --git a/wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java b/src/org/jgrapht/alg/EdmondsBlossomShrinking.java similarity index 100% rename from wdl/org/jgrapht/alg/EdmondsBlossomShrinking.java rename to src/org/jgrapht/alg/EdmondsBlossomShrinking.java diff --git a/wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java b/src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java similarity index 100% rename from wdl/org/jgrapht/alg/EdmondsKarpMaximumFlow.java rename to src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java diff --git a/wdl/org/jgrapht/alg/EulerianCircuit.java b/src/org/jgrapht/alg/EulerianCircuit.java similarity index 100% rename from wdl/org/jgrapht/alg/EulerianCircuit.java rename to src/org/jgrapht/alg/EulerianCircuit.java diff --git a/wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java b/src/org/jgrapht/alg/FloydWarshallShortestPaths.java similarity index 100% rename from wdl/org/jgrapht/alg/FloydWarshallShortestPaths.java rename to src/org/jgrapht/alg/FloydWarshallShortestPaths.java diff --git a/wdl/org/jgrapht/alg/HamiltonianCycle.java b/src/org/jgrapht/alg/HamiltonianCycle.java similarity index 100% rename from wdl/org/jgrapht/alg/HamiltonianCycle.java rename to src/org/jgrapht/alg/HamiltonianCycle.java diff --git a/wdl/org/jgrapht/alg/KShortestPaths.java b/src/org/jgrapht/alg/KShortestPaths.java similarity index 100% rename from wdl/org/jgrapht/alg/KShortestPaths.java rename to src/org/jgrapht/alg/KShortestPaths.java diff --git a/wdl/org/jgrapht/alg/KShortestPathsIterator.java b/src/org/jgrapht/alg/KShortestPathsIterator.java similarity index 100% rename from wdl/org/jgrapht/alg/KShortestPathsIterator.java rename to src/org/jgrapht/alg/KShortestPathsIterator.java diff --git a/wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java b/src/org/jgrapht/alg/KruskalMinimumSpanningTree.java similarity index 100% rename from wdl/org/jgrapht/alg/KruskalMinimumSpanningTree.java rename to src/org/jgrapht/alg/KruskalMinimumSpanningTree.java diff --git a/wdl/org/jgrapht/alg/NeighborIndex.java b/src/org/jgrapht/alg/NeighborIndex.java similarity index 100% rename from wdl/org/jgrapht/alg/NeighborIndex.java rename to src/org/jgrapht/alg/NeighborIndex.java diff --git a/wdl/org/jgrapht/alg/RankingPathElement.java b/src/org/jgrapht/alg/RankingPathElement.java similarity index 100% rename from wdl/org/jgrapht/alg/RankingPathElement.java rename to src/org/jgrapht/alg/RankingPathElement.java diff --git a/wdl/org/jgrapht/alg/RankingPathElementList.java b/src/org/jgrapht/alg/RankingPathElementList.java similarity index 100% rename from wdl/org/jgrapht/alg/RankingPathElementList.java rename to src/org/jgrapht/alg/RankingPathElementList.java diff --git a/wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java b/src/org/jgrapht/alg/StoerWagnerMinimumCut.java similarity index 100% rename from wdl/org/jgrapht/alg/StoerWagnerMinimumCut.java rename to src/org/jgrapht/alg/StoerWagnerMinimumCut.java diff --git a/wdl/org/jgrapht/alg/StrongConnectivityInspector.java b/src/org/jgrapht/alg/StrongConnectivityInspector.java similarity index 100% rename from wdl/org/jgrapht/alg/StrongConnectivityInspector.java rename to src/org/jgrapht/alg/StrongConnectivityInspector.java diff --git a/wdl/org/jgrapht/alg/TransitiveClosure.java b/src/org/jgrapht/alg/TransitiveClosure.java similarity index 100% rename from wdl/org/jgrapht/alg/TransitiveClosure.java rename to src/org/jgrapht/alg/TransitiveClosure.java diff --git a/wdl/org/jgrapht/alg/VertexCovers.java b/src/org/jgrapht/alg/VertexCovers.java similarity index 100% rename from wdl/org/jgrapht/alg/VertexCovers.java rename to src/org/jgrapht/alg/VertexCovers.java diff --git a/wdl/org/jgrapht/alg/package.html b/src/org/jgrapht/alg/package.html similarity index 100% rename from wdl/org/jgrapht/alg/package.html rename to src/org/jgrapht/alg/package.html diff --git a/wdl/org/jgrapht/alg/util/UnionFind.java b/src/org/jgrapht/alg/util/UnionFind.java similarity index 100% rename from wdl/org/jgrapht/alg/util/UnionFind.java rename to src/org/jgrapht/alg/util/UnionFind.java diff --git a/wdl/org/jgrapht/alg/util/VertexDegreeComparator.java b/src/org/jgrapht/alg/util/VertexDegreeComparator.java similarity index 100% rename from wdl/org/jgrapht/alg/util/VertexDegreeComparator.java rename to src/org/jgrapht/alg/util/VertexDegreeComparator.java diff --git a/wdl/org/jgrapht/alg/util/package.html b/src/org/jgrapht/alg/util/package.html similarity index 100% rename from wdl/org/jgrapht/alg/util/package.html rename to src/org/jgrapht/alg/util/package.html diff --git a/wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java b/src/org/jgrapht/event/ConnectedComponentTraversalEvent.java similarity index 100% rename from wdl/org/jgrapht/event/ConnectedComponentTraversalEvent.java rename to src/org/jgrapht/event/ConnectedComponentTraversalEvent.java diff --git a/wdl/org/jgrapht/event/EdgeTraversalEvent.java b/src/org/jgrapht/event/EdgeTraversalEvent.java similarity index 100% rename from wdl/org/jgrapht/event/EdgeTraversalEvent.java rename to src/org/jgrapht/event/EdgeTraversalEvent.java diff --git a/wdl/org/jgrapht/event/GraphChangeEvent.java b/src/org/jgrapht/event/GraphChangeEvent.java similarity index 100% rename from wdl/org/jgrapht/event/GraphChangeEvent.java rename to src/org/jgrapht/event/GraphChangeEvent.java diff --git a/wdl/org/jgrapht/event/GraphEdgeChangeEvent.java b/src/org/jgrapht/event/GraphEdgeChangeEvent.java similarity index 100% rename from wdl/org/jgrapht/event/GraphEdgeChangeEvent.java rename to src/org/jgrapht/event/GraphEdgeChangeEvent.java diff --git a/wdl/org/jgrapht/event/GraphListener.java b/src/org/jgrapht/event/GraphListener.java similarity index 100% rename from wdl/org/jgrapht/event/GraphListener.java rename to src/org/jgrapht/event/GraphListener.java diff --git a/wdl/org/jgrapht/event/GraphVertexChangeEvent.java b/src/org/jgrapht/event/GraphVertexChangeEvent.java similarity index 100% rename from wdl/org/jgrapht/event/GraphVertexChangeEvent.java rename to src/org/jgrapht/event/GraphVertexChangeEvent.java diff --git a/wdl/org/jgrapht/event/TraversalListener.java b/src/org/jgrapht/event/TraversalListener.java similarity index 100% rename from wdl/org/jgrapht/event/TraversalListener.java rename to src/org/jgrapht/event/TraversalListener.java diff --git a/wdl/org/jgrapht/event/TraversalListenerAdapter.java b/src/org/jgrapht/event/TraversalListenerAdapter.java similarity index 100% rename from wdl/org/jgrapht/event/TraversalListenerAdapter.java rename to src/org/jgrapht/event/TraversalListenerAdapter.java diff --git a/wdl/org/jgrapht/event/VertexSetListener.java b/src/org/jgrapht/event/VertexSetListener.java similarity index 100% rename from wdl/org/jgrapht/event/VertexSetListener.java rename to src/org/jgrapht/event/VertexSetListener.java diff --git a/wdl/org/jgrapht/event/VertexTraversalEvent.java b/src/org/jgrapht/event/VertexTraversalEvent.java similarity index 100% rename from wdl/org/jgrapht/event/VertexTraversalEvent.java rename to src/org/jgrapht/event/VertexTraversalEvent.java diff --git a/wdl/org/jgrapht/event/package.html b/src/org/jgrapht/event/package.html similarity index 100% rename from wdl/org/jgrapht/event/package.html rename to src/org/jgrapht/event/package.html diff --git a/wdl/org/jgrapht/experimental/GraphReader.java b/src/org/jgrapht/experimental/GraphReader.java similarity index 100% rename from wdl/org/jgrapht/experimental/GraphReader.java rename to src/org/jgrapht/experimental/GraphReader.java diff --git a/wdl/org/jgrapht/experimental/GraphSquare.java b/src/org/jgrapht/experimental/GraphSquare.java similarity index 100% rename from wdl/org/jgrapht/experimental/GraphSquare.java rename to src/org/jgrapht/experimental/GraphSquare.java diff --git a/wdl/org/jgrapht/experimental/GraphTests.java b/src/org/jgrapht/experimental/GraphTests.java similarity index 100% rename from wdl/org/jgrapht/experimental/GraphTests.java rename to src/org/jgrapht/experimental/GraphTests.java diff --git a/wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java b/src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/experimental/PartiteRandomGraphGenerator.java rename to src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java diff --git a/wdl/org/jgrapht/experimental/RandomGraphHelper.java b/src/org/jgrapht/experimental/RandomGraphHelper.java similarity index 100% rename from wdl/org/jgrapht/experimental/RandomGraphHelper.java rename to src/org/jgrapht/experimental/RandomGraphHelper.java diff --git a/wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java b/src/org/jgrapht/experimental/UniformRandomGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/experimental/UniformRandomGraphGenerator.java rename to src/org/jgrapht/experimental/UniformRandomGraphGenerator.java diff --git a/wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java b/src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java similarity index 100% rename from wdl/org/jgrapht/experimental/alg/ApproximationAlgorithm.java rename to src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java b/src/org/jgrapht/experimental/alg/ExactAlgorithm.java similarity index 100% rename from wdl/org/jgrapht/experimental/alg/ExactAlgorithm.java rename to src/org/jgrapht/experimental/alg/ExactAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java b/src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java similarity index 100% rename from wdl/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java rename to src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java diff --git a/wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java b/src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java similarity index 100% rename from wdl/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java rename to src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java diff --git a/wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java b/src/org/jgrapht/experimental/alg/color/GreedyColoring.java similarity index 100% rename from wdl/org/jgrapht/experimental/alg/color/GreedyColoring.java rename to src/org/jgrapht/experimental/alg/color/GreedyColoring.java diff --git a/wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java b/src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java similarity index 100% rename from wdl/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java rename to src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/EquivalenceComparator.java rename to src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java rename to src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java rename to src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java b/src/org/jgrapht/experimental/equivalence/EquivalenceSet.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/EquivalenceSet.java rename to src/org/jgrapht/experimental/equivalence/EquivalenceSet.java diff --git a/wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java b/src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java rename to src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java b/src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java rename to src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/equivalence/package.html b/src/org/jgrapht/experimental/equivalence/package.html similarity index 100% rename from wdl/org/jgrapht/experimental/equivalence/package.html rename to src/org/jgrapht/experimental/equivalence/package.html diff --git a/wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java rename to src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java b/src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java rename to src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java rename to src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java rename to src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java b/src/org/jgrapht/experimental/isomorphism/GraphOrdering.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/GraphOrdering.java rename to src/org/jgrapht/experimental/isomorphism/GraphOrdering.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java b/src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java rename to src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java rename to src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java b/src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java rename to src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java diff --git a/wdl/org/jgrapht/experimental/isomorphism/package.html b/src/org/jgrapht/experimental/isomorphism/package.html similarity index 100% rename from wdl/org/jgrapht/experimental/isomorphism/package.html rename to src/org/jgrapht/experimental/isomorphism/package.html diff --git a/wdl/org/jgrapht/experimental/package.html b/src/org/jgrapht/experimental/package.html similarity index 100% rename from wdl/org/jgrapht/experimental/package.html rename to src/org/jgrapht/experimental/package.html diff --git a/wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java b/src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java rename to src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java b/src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/CollectionPermutationIter.java rename to src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java b/src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/CompoundPermutationIter.java rename to src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java b/src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/IntegerPermutationIter.java rename to src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java diff --git a/wdl/org/jgrapht/experimental/permutation/PermutationFactory.java b/src/org/jgrapht/experimental/permutation/PermutationFactory.java similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/PermutationFactory.java rename to src/org/jgrapht/experimental/permutation/PermutationFactory.java diff --git a/wdl/org/jgrapht/experimental/permutation/package.html b/src/org/jgrapht/experimental/permutation/package.html similarity index 100% rename from wdl/org/jgrapht/experimental/permutation/package.html rename to src/org/jgrapht/experimental/permutation/package.html diff --git a/wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java b/src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java rename to src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/CompleteGraphGenerator.java b/src/org/jgrapht/generate/CompleteGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/CompleteGraphGenerator.java rename to src/org/jgrapht/generate/CompleteGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/EmptyGraphGenerator.java b/src/org/jgrapht/generate/EmptyGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/EmptyGraphGenerator.java rename to src/org/jgrapht/generate/EmptyGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/GraphGenerator.java b/src/org/jgrapht/generate/GraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/GraphGenerator.java rename to src/org/jgrapht/generate/GraphGenerator.java diff --git a/wdl/org/jgrapht/generate/GridGraphGenerator.java b/src/org/jgrapht/generate/GridGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/GridGraphGenerator.java rename to src/org/jgrapht/generate/GridGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java b/src/org/jgrapht/generate/HyperCubeGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/HyperCubeGraphGenerator.java rename to src/org/jgrapht/generate/HyperCubeGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/LinearGraphGenerator.java b/src/org/jgrapht/generate/LinearGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/LinearGraphGenerator.java rename to src/org/jgrapht/generate/LinearGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/RandomGraphGenerator.java b/src/org/jgrapht/generate/RandomGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/RandomGraphGenerator.java rename to src/org/jgrapht/generate/RandomGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/RingGraphGenerator.java b/src/org/jgrapht/generate/RingGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/RingGraphGenerator.java rename to src/org/jgrapht/generate/RingGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java b/src/org/jgrapht/generate/ScaleFreeGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/ScaleFreeGraphGenerator.java rename to src/org/jgrapht/generate/ScaleFreeGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/StarGraphGenerator.java b/src/org/jgrapht/generate/StarGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/StarGraphGenerator.java rename to src/org/jgrapht/generate/StarGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/WheelGraphGenerator.java b/src/org/jgrapht/generate/WheelGraphGenerator.java similarity index 100% rename from wdl/org/jgrapht/generate/WheelGraphGenerator.java rename to src/org/jgrapht/generate/WheelGraphGenerator.java diff --git a/wdl/org/jgrapht/generate/package.html b/src/org/jgrapht/generate/package.html similarity index 100% rename from wdl/org/jgrapht/generate/package.html rename to src/org/jgrapht/generate/package.html diff --git a/wdl/org/jgrapht/graph/AbstractBaseGraph.java b/src/org/jgrapht/graph/AbstractBaseGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AbstractBaseGraph.java rename to src/org/jgrapht/graph/AbstractBaseGraph.java diff --git a/wdl/org/jgrapht/graph/AbstractGraph.java b/src/org/jgrapht/graph/AbstractGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AbstractGraph.java rename to src/org/jgrapht/graph/AbstractGraph.java diff --git a/wdl/org/jgrapht/graph/AsUndirectedGraph.java b/src/org/jgrapht/graph/AsUndirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AsUndirectedGraph.java rename to src/org/jgrapht/graph/AsUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java b/src/org/jgrapht/graph/AsUnweightedDirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AsUnweightedDirectedGraph.java rename to src/org/jgrapht/graph/AsUnweightedDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/AsUnweightedGraph.java b/src/org/jgrapht/graph/AsUnweightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AsUnweightedGraph.java rename to src/org/jgrapht/graph/AsUnweightedGraph.java diff --git a/wdl/org/jgrapht/graph/AsWeightedGraph.java b/src/org/jgrapht/graph/AsWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/AsWeightedGraph.java rename to src/org/jgrapht/graph/AsWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java b/src/org/jgrapht/graph/ClassBasedEdgeFactory.java similarity index 100% rename from wdl/org/jgrapht/graph/ClassBasedEdgeFactory.java rename to src/org/jgrapht/graph/ClassBasedEdgeFactory.java diff --git a/wdl/org/jgrapht/graph/ClassBasedVertexFactory.java b/src/org/jgrapht/graph/ClassBasedVertexFactory.java similarity index 100% rename from wdl/org/jgrapht/graph/ClassBasedVertexFactory.java rename to src/org/jgrapht/graph/ClassBasedVertexFactory.java diff --git a/wdl/org/jgrapht/graph/DefaultDirectedGraph.java b/src/org/jgrapht/graph/DefaultDirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultDirectedGraph.java rename to src/org/jgrapht/graph/DefaultDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java b/src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultDirectedWeightedGraph.java rename to src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultEdge.java b/src/org/jgrapht/graph/DefaultEdge.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultEdge.java rename to src/org/jgrapht/graph/DefaultEdge.java diff --git a/wdl/org/jgrapht/graph/DefaultGraphMapping.java b/src/org/jgrapht/graph/DefaultGraphMapping.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultGraphMapping.java rename to src/org/jgrapht/graph/DefaultGraphMapping.java diff --git a/wdl/org/jgrapht/graph/DefaultListenableGraph.java b/src/org/jgrapht/graph/DefaultListenableGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultListenableGraph.java rename to src/org/jgrapht/graph/DefaultListenableGraph.java diff --git a/wdl/org/jgrapht/graph/DefaultWeightedEdge.java b/src/org/jgrapht/graph/DefaultWeightedEdge.java similarity index 100% rename from wdl/org/jgrapht/graph/DefaultWeightedEdge.java rename to src/org/jgrapht/graph/DefaultWeightedEdge.java diff --git a/wdl/org/jgrapht/graph/DirectedGraphUnion.java b/src/org/jgrapht/graph/DirectedGraphUnion.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedGraphUnion.java rename to src/org/jgrapht/graph/DirectedGraphUnion.java diff --git a/wdl/org/jgrapht/graph/DirectedMaskSubgraph.java b/src/org/jgrapht/graph/DirectedMaskSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedMaskSubgraph.java rename to src/org/jgrapht/graph/DirectedMaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/DirectedMultigraph.java b/src/org/jgrapht/graph/DirectedMultigraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedMultigraph.java rename to src/org/jgrapht/graph/DirectedMultigraph.java diff --git a/wdl/org/jgrapht/graph/DirectedPseudograph.java b/src/org/jgrapht/graph/DirectedPseudograph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedPseudograph.java rename to src/org/jgrapht/graph/DirectedPseudograph.java diff --git a/wdl/org/jgrapht/graph/DirectedSubgraph.java b/src/org/jgrapht/graph/DirectedSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedSubgraph.java rename to src/org/jgrapht/graph/DirectedSubgraph.java diff --git a/wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java b/src/org/jgrapht/graph/DirectedWeightedMultigraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedWeightedMultigraph.java rename to src/org/jgrapht/graph/DirectedWeightedMultigraph.java diff --git a/wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java b/src/org/jgrapht/graph/DirectedWeightedSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/DirectedWeightedSubgraph.java rename to src/org/jgrapht/graph/DirectedWeightedSubgraph.java diff --git a/wdl/org/jgrapht/graph/EdgeReversedGraph.java b/src/org/jgrapht/graph/EdgeReversedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/EdgeReversedGraph.java rename to src/org/jgrapht/graph/EdgeReversedGraph.java diff --git a/wdl/org/jgrapht/graph/EdgeSetFactory.java b/src/org/jgrapht/graph/EdgeSetFactory.java similarity index 100% rename from wdl/org/jgrapht/graph/EdgeSetFactory.java rename to src/org/jgrapht/graph/EdgeSetFactory.java diff --git a/wdl/org/jgrapht/graph/GraphDelegator.java b/src/org/jgrapht/graph/GraphDelegator.java similarity index 100% rename from wdl/org/jgrapht/graph/GraphDelegator.java rename to src/org/jgrapht/graph/GraphDelegator.java diff --git a/wdl/org/jgrapht/graph/GraphPathImpl.java b/src/org/jgrapht/graph/GraphPathImpl.java similarity index 100% rename from wdl/org/jgrapht/graph/GraphPathImpl.java rename to src/org/jgrapht/graph/GraphPathImpl.java diff --git a/wdl/org/jgrapht/graph/GraphUnion.java b/src/org/jgrapht/graph/GraphUnion.java similarity index 100% rename from wdl/org/jgrapht/graph/GraphUnion.java rename to src/org/jgrapht/graph/GraphUnion.java diff --git a/wdl/org/jgrapht/graph/IntrusiveEdge.java b/src/org/jgrapht/graph/IntrusiveEdge.java similarity index 100% rename from wdl/org/jgrapht/graph/IntrusiveEdge.java rename to src/org/jgrapht/graph/IntrusiveEdge.java diff --git a/wdl/org/jgrapht/graph/ListenableDirectedGraph.java b/src/org/jgrapht/graph/ListenableDirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/ListenableDirectedGraph.java rename to src/org/jgrapht/graph/ListenableDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java b/src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/ListenableDirectedWeightedGraph.java rename to src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableUndirectedGraph.java b/src/org/jgrapht/graph/ListenableUndirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/ListenableUndirectedGraph.java rename to src/org/jgrapht/graph/ListenableUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java b/src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java rename to src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/MaskEdgeSet.java b/src/org/jgrapht/graph/MaskEdgeSet.java similarity index 100% rename from wdl/org/jgrapht/graph/MaskEdgeSet.java rename to src/org/jgrapht/graph/MaskEdgeSet.java diff --git a/wdl/org/jgrapht/graph/MaskFunctor.java b/src/org/jgrapht/graph/MaskFunctor.java similarity index 100% rename from wdl/org/jgrapht/graph/MaskFunctor.java rename to src/org/jgrapht/graph/MaskFunctor.java diff --git a/wdl/org/jgrapht/graph/MaskSubgraph.java b/src/org/jgrapht/graph/MaskSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/MaskSubgraph.java rename to src/org/jgrapht/graph/MaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/MaskVertexSet.java b/src/org/jgrapht/graph/MaskVertexSet.java similarity index 100% rename from wdl/org/jgrapht/graph/MaskVertexSet.java rename to src/org/jgrapht/graph/MaskVertexSet.java diff --git a/wdl/org/jgrapht/graph/Multigraph.java b/src/org/jgrapht/graph/Multigraph.java similarity index 100% rename from wdl/org/jgrapht/graph/Multigraph.java rename to src/org/jgrapht/graph/Multigraph.java diff --git a/wdl/org/jgrapht/graph/ParanoidGraph.java b/src/org/jgrapht/graph/ParanoidGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/ParanoidGraph.java rename to src/org/jgrapht/graph/ParanoidGraph.java diff --git a/wdl/org/jgrapht/graph/Pseudograph.java b/src/org/jgrapht/graph/Pseudograph.java similarity index 100% rename from wdl/org/jgrapht/graph/Pseudograph.java rename to src/org/jgrapht/graph/Pseudograph.java diff --git a/wdl/org/jgrapht/graph/SimpleDirectedGraph.java b/src/org/jgrapht/graph/SimpleDirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/SimpleDirectedGraph.java rename to src/org/jgrapht/graph/SimpleDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java b/src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/SimpleDirectedWeightedGraph.java rename to src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleGraph.java b/src/org/jgrapht/graph/SimpleGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/SimpleGraph.java rename to src/org/jgrapht/graph/SimpleGraph.java diff --git a/wdl/org/jgrapht/graph/SimpleWeightedGraph.java b/src/org/jgrapht/graph/SimpleWeightedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/SimpleWeightedGraph.java rename to src/org/jgrapht/graph/SimpleWeightedGraph.java diff --git a/wdl/org/jgrapht/graph/Subgraph.java b/src/org/jgrapht/graph/Subgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/Subgraph.java rename to src/org/jgrapht/graph/Subgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedGraphUnion.java b/src/org/jgrapht/graph/UndirectedGraphUnion.java similarity index 100% rename from wdl/org/jgrapht/graph/UndirectedGraphUnion.java rename to src/org/jgrapht/graph/UndirectedGraphUnion.java diff --git a/wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java b/src/org/jgrapht/graph/UndirectedMaskSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UndirectedMaskSubgraph.java rename to src/org/jgrapht/graph/UndirectedMaskSubgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedSubgraph.java b/src/org/jgrapht/graph/UndirectedSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UndirectedSubgraph.java rename to src/org/jgrapht/graph/UndirectedSubgraph.java diff --git a/wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java b/src/org/jgrapht/graph/UndirectedWeightedSubgraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UndirectedWeightedSubgraph.java rename to src/org/jgrapht/graph/UndirectedWeightedSubgraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java b/src/org/jgrapht/graph/UnmodifiableDirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UnmodifiableDirectedGraph.java rename to src/org/jgrapht/graph/UnmodifiableDirectedGraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableGraph.java b/src/org/jgrapht/graph/UnmodifiableGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UnmodifiableGraph.java rename to src/org/jgrapht/graph/UnmodifiableGraph.java diff --git a/wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java b/src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java similarity index 100% rename from wdl/org/jgrapht/graph/UnmodifiableUndirectedGraph.java rename to src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java diff --git a/wdl/org/jgrapht/graph/WeightedMultigraph.java b/src/org/jgrapht/graph/WeightedMultigraph.java similarity index 100% rename from wdl/org/jgrapht/graph/WeightedMultigraph.java rename to src/org/jgrapht/graph/WeightedMultigraph.java diff --git a/wdl/org/jgrapht/graph/WeightedPseudograph.java b/src/org/jgrapht/graph/WeightedPseudograph.java similarity index 100% rename from wdl/org/jgrapht/graph/WeightedPseudograph.java rename to src/org/jgrapht/graph/WeightedPseudograph.java diff --git a/wdl/org/jgrapht/graph/package.html b/src/org/jgrapht/graph/package.html similarity index 100% rename from wdl/org/jgrapht/graph/package.html rename to src/org/jgrapht/graph/package.html diff --git a/wdl/org/jgrapht/package.html b/src/org/jgrapht/package.html similarity index 100% rename from wdl/org/jgrapht/package.html rename to src/org/jgrapht/package.html diff --git a/wdl/org/jgrapht/traverse/AbstractGraphIterator.java b/src/org/jgrapht/traverse/AbstractGraphIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/AbstractGraphIterator.java rename to src/org/jgrapht/traverse/AbstractGraphIterator.java diff --git a/wdl/org/jgrapht/traverse/BreadthFirstIterator.java b/src/org/jgrapht/traverse/BreadthFirstIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/BreadthFirstIterator.java rename to src/org/jgrapht/traverse/BreadthFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/ClosestFirstIterator.java b/src/org/jgrapht/traverse/ClosestFirstIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/ClosestFirstIterator.java rename to src/org/jgrapht/traverse/ClosestFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/CrossComponentIterator.java b/src/org/jgrapht/traverse/CrossComponentIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/CrossComponentIterator.java rename to src/org/jgrapht/traverse/CrossComponentIterator.java diff --git a/wdl/org/jgrapht/traverse/DepthFirstIterator.java b/src/org/jgrapht/traverse/DepthFirstIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/DepthFirstIterator.java rename to src/org/jgrapht/traverse/DepthFirstIterator.java diff --git a/wdl/org/jgrapht/traverse/GraphIterator.java b/src/org/jgrapht/traverse/GraphIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/GraphIterator.java rename to src/org/jgrapht/traverse/GraphIterator.java diff --git a/wdl/org/jgrapht/traverse/TopologicalOrderIterator.java b/src/org/jgrapht/traverse/TopologicalOrderIterator.java similarity index 100% rename from wdl/org/jgrapht/traverse/TopologicalOrderIterator.java rename to src/org/jgrapht/traverse/TopologicalOrderIterator.java diff --git a/wdl/org/jgrapht/traverse/package.html b/src/org/jgrapht/traverse/package.html similarity index 100% rename from wdl/org/jgrapht/traverse/package.html rename to src/org/jgrapht/traverse/package.html diff --git a/wdl/org/jgrapht/util/ArrayUnenforcedSet.java b/src/org/jgrapht/util/ArrayUnenforcedSet.java similarity index 100% rename from wdl/org/jgrapht/util/ArrayUnenforcedSet.java rename to src/org/jgrapht/util/ArrayUnenforcedSet.java diff --git a/wdl/org/jgrapht/util/FibonacciHeap.java b/src/org/jgrapht/util/FibonacciHeap.java similarity index 100% rename from wdl/org/jgrapht/util/FibonacciHeap.java rename to src/org/jgrapht/util/FibonacciHeap.java diff --git a/wdl/org/jgrapht/util/FibonacciHeapNode.java b/src/org/jgrapht/util/FibonacciHeapNode.java similarity index 100% rename from wdl/org/jgrapht/util/FibonacciHeapNode.java rename to src/org/jgrapht/util/FibonacciHeapNode.java diff --git a/wdl/org/jgrapht/util/MathUtil.java b/src/org/jgrapht/util/MathUtil.java similarity index 100% rename from wdl/org/jgrapht/util/MathUtil.java rename to src/org/jgrapht/util/MathUtil.java diff --git a/wdl/org/jgrapht/util/ModifiableInteger.java b/src/org/jgrapht/util/ModifiableInteger.java similarity index 100% rename from wdl/org/jgrapht/util/ModifiableInteger.java rename to src/org/jgrapht/util/ModifiableInteger.java diff --git a/wdl/org/jgrapht/util/PrefetchIterator.java b/src/org/jgrapht/util/PrefetchIterator.java similarity index 100% rename from wdl/org/jgrapht/util/PrefetchIterator.java rename to src/org/jgrapht/util/PrefetchIterator.java diff --git a/wdl/org/jgrapht/util/TypeUtil.java b/src/org/jgrapht/util/TypeUtil.java similarity index 100% rename from wdl/org/jgrapht/util/TypeUtil.java rename to src/org/jgrapht/util/TypeUtil.java diff --git a/wdl/org/jgrapht/util/VertexPair.java b/src/org/jgrapht/util/VertexPair.java similarity index 100% rename from wdl/org/jgrapht/util/VertexPair.java rename to src/org/jgrapht/util/VertexPair.java diff --git a/wdl/org/jgrapht/util/WeightCombiner.java b/src/org/jgrapht/util/WeightCombiner.java similarity index 100% rename from wdl/org/jgrapht/util/WeightCombiner.java rename to src/org/jgrapht/util/WeightCombiner.java diff --git a/wdl/org/jgrapht/util/package.html b/src/org/jgrapht/util/package.html similarity index 100% rename from wdl/org/jgrapht/util/package.html rename to src/org/jgrapht/util/package.html diff --git a/wdl/wdl.zgr b/src/wdl.zgr similarity index 100% rename from wdl/wdl.zgr rename to src/wdl.zgr From 744ff6d8f5c4026a00c96bfe7ea3b118db95cee5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 11:48:33 -0400 Subject: [PATCH 057/140] Adding build file --- build.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 build.xml diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..e88584f --- /dev/null +++ b/build.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From ccb000f6b773fcc0ddffc5559d86c7339b18fa8e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 11:53:37 -0400 Subject: [PATCH 058/140] moving README --- README.md | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/README.md | 233 --------------------------------------------------------- 2 files changed, 232 insertions(+), 237 deletions(-) delete mode 100644 src/README.md diff --git a/README.md b/README.md index fe78002..2c2d2d9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,233 @@ -Workflow Description Language -============================= +Usage +===== -* `./dot` - Contains a DOT Language parser -* `./wdl` - Contains a WDL parser +There are two example .wdl files in the examples/ directory: + +* MutSig.wdl +* CopyNumberQC.wdl + +From Java code, the main interface is the CompositeTask, which can be used in this example to acquire the name of each task: + +```java +CompositeTask ct = new CompositeTask(new File(args[0])); +for ( CompositeTaskNode entry : ct.getNodes() ) { + System.out.println("Node: " + entry); +} +``` + +Compiling is relatively straightforward: +``` +$ javac *.java +``` + +The data file we'll use is: + +``` +composite_task test { + step s0[version=0] { + output: File("abc") as foo; + } + + for (I in L) { + for (J in M) { + step s1[version=0] { + input: p0=I, p1=J, p2=foo; + output: File("def") as bar; + } + } + } + + step s2[version=0] { + input: p0=bar; + } +} +``` + +Get the abstract syntax tree: + +``` +$ java WdlMain examples/7.wdl ast +(CompositeTask: + body=[ + (Step: + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (ForLoop: + body=[ + (ForLoop: + body=[ + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + item=identifier, + collection=identifier + ) + ], + item=identifier, + collection=identifier + ), + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + name=identifier +) +``` + +Get a view of the graph + +``` +$ java WdlMain examples/7.wdl graph +VERTICIES +--------- +[Step: name=s1] +[Variable: name=J] +[Variable: name=M] +[Variable: name=I] +[Variable: name=L] +[Variable: name=foo] +[Step: name=s0] +[Variable: name=bar] +[Step: name=s2] +[CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Variable: name=I] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Step: name=s2] +] +[Edge + from: [Variable: name=J] + to: [Step: name=s1] +] +[Edge + from: [Variable: name=L] + to: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] +] +[Edge + from: [Variable: name=foo] + to: [Step: name=s1] +] +[Edge + from: [Variable: name=I] + to: [Step: name=s1] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + to: [Variable: name=J] +] +[Edge + from: [Step: name=s0] + to: [Variable: name=foo] +] +[Edge + from: [Step: name=s1] + to: [Variable: name=bar] +] +[Edge + from: [Variable: name=bar] + to: [Step: name=s2] +] +[Edge + from: [Variable: name=M] + to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] +] +``` diff --git a/src/README.md b/src/README.md deleted file mode 100644 index 2c2d2d9..0000000 --- a/src/README.md +++ /dev/null @@ -1,233 +0,0 @@ -Usage -===== - -There are two example .wdl files in the examples/ directory: - -* MutSig.wdl -* CopyNumberQC.wdl - -From Java code, the main interface is the CompositeTask, which can be used in this example to acquire the name of each task: - -```java -CompositeTask ct = new CompositeTask(new File(args[0])); -for ( CompositeTaskNode entry : ct.getNodes() ) { - System.out.println("Node: " + entry); -} -``` - -Compiling is relatively straightforward: -``` -$ javac *.java -``` - -The data file we'll use is: - -``` -composite_task test { - step s0[version=0] { - output: File("abc") as foo; - } - - for (I in L) { - for (J in M) { - step s1[version=0] { - input: p0=I, p1=J, p2=foo; - output: File("def") as bar; - } - } - } - - step s2[version=0] { - input: p0=bar; - } -} -``` - -Get the abstract syntax tree: - -``` -$ java WdlMain examples/7.wdl ast -(CompositeTask: - body=[ - (Step: - body=[ - (StepOutputList: - outputs=[ - (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string - ) - ] - ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None - ), - (ForLoop: - body=[ - (ForLoop: - body=[ - (Step: - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string - ) - ] - ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None - ) - ], - item=identifier, - collection=identifier - ) - ], - item=identifier, - collection=identifier - ), - (Step: - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - member=None, - name=identifier - ) - ) - ] - ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None - ) - ], - name=identifier -) -``` - -Get a view of the graph - -``` -$ java WdlMain examples/7.wdl graph -VERTICIES ---------- -[Step: name=s1] -[Variable: name=J] -[Variable: name=M] -[Variable: name=I] -[Variable: name=L] -[Variable: name=foo] -[Step: name=s0] -[Variable: name=bar] -[Step: name=s2] -[CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] -[CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] - -EDGES ------ -[Edge - from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] - to: [Variable: name=I] -] -[Edge - from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] - to: [Step: name=s2] -] -[Edge - from: [Variable: name=J] - to: [Step: name=s1] -] -[Edge - from: [Variable: name=L] - to: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] -] -[Edge - from: [Variable: name=foo] - to: [Step: name=s1] -] -[Edge - from: [Variable: name=I] - to: [Step: name=s1] -] -[Edge - from: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] - to: [Variable: name=J] -] -[Edge - from: [Step: name=s0] - to: [Variable: name=foo] -] -[Edge - from: [Step: name=s1] - to: [Variable: name=bar] -] -[Edge - from: [Variable: name=bar] - to: [Step: name=s2] -] -[Edge - from: [Variable: name=M] - to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] -] -``` From f6972acf0d08219f5855a5149615f47fc7c7213f Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 12:56:43 -0300 Subject: [PATCH 059/140] Update README.md --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 2c2d2d9..4880cc8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ +Workflow Description Language (wdl) +=================================== + +The Workflow Description Language is a language for describing dependency trees of tasks (algorithms) in a concise and clear syntax. + +Installation +============ + +To build the JAR file, run: + +``` +$ ant dist +``` + +Which will create a file dist/Wdl-${version}.jar + Usage ===== From 02d7261ef3eb7092d88529ca72acf5c439b1bb93 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 13:04:51 -0400 Subject: [PATCH 060/140] reorganizing --- {src/examples => examples}/0.wdl | 0 {src/examples => examples}/1.wdl | 0 {src/examples => examples}/2.wdl | 0 {src/examples => examples}/3.wdl | 0 {src/examples => examples}/4.wdl | 0 {src/examples => examples}/5.wdl | 0 {src/examples => examples}/6.wdl | 0 {src/examples => examples}/7.wdl | 0 {src/examples => examples}/CopyNumberQC.wdl | 0 {src/examples => examples}/MutSig.wdl | 0 {src/examples => examples}/simple.wdl | 0 {src => grammars}/wdl.zgr | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename {src/examples => examples}/0.wdl (100%) rename {src/examples => examples}/1.wdl (100%) rename {src/examples => examples}/2.wdl (100%) rename {src/examples => examples}/3.wdl (100%) rename {src/examples => examples}/4.wdl (100%) rename {src/examples => examples}/5.wdl (100%) rename {src/examples => examples}/6.wdl (100%) rename {src/examples => examples}/7.wdl (100%) rename {src/examples => examples}/CopyNumberQC.wdl (100%) rename {src/examples => examples}/MutSig.wdl (100%) rename {src/examples => examples}/simple.wdl (100%) rename {src => grammars}/wdl.zgr (100%) diff --git a/src/examples/0.wdl b/examples/0.wdl similarity index 100% rename from src/examples/0.wdl rename to examples/0.wdl diff --git a/src/examples/1.wdl b/examples/1.wdl similarity index 100% rename from src/examples/1.wdl rename to examples/1.wdl diff --git a/src/examples/2.wdl b/examples/2.wdl similarity index 100% rename from src/examples/2.wdl rename to examples/2.wdl diff --git a/src/examples/3.wdl b/examples/3.wdl similarity index 100% rename from src/examples/3.wdl rename to examples/3.wdl diff --git a/src/examples/4.wdl b/examples/4.wdl similarity index 100% rename from src/examples/4.wdl rename to examples/4.wdl diff --git a/src/examples/5.wdl b/examples/5.wdl similarity index 100% rename from src/examples/5.wdl rename to examples/5.wdl diff --git a/src/examples/6.wdl b/examples/6.wdl similarity index 100% rename from src/examples/6.wdl rename to examples/6.wdl diff --git a/src/examples/7.wdl b/examples/7.wdl similarity index 100% rename from src/examples/7.wdl rename to examples/7.wdl diff --git a/src/examples/CopyNumberQC.wdl b/examples/CopyNumberQC.wdl similarity index 100% rename from src/examples/CopyNumberQC.wdl rename to examples/CopyNumberQC.wdl diff --git a/src/examples/MutSig.wdl b/examples/MutSig.wdl similarity index 100% rename from src/examples/MutSig.wdl rename to examples/MutSig.wdl diff --git a/src/examples/simple.wdl b/examples/simple.wdl similarity index 100% rename from src/examples/simple.wdl rename to examples/simple.wdl diff --git a/src/wdl.zgr b/grammars/wdl.zgr similarity index 100% rename from src/wdl.zgr rename to grammars/wdl.zgr From 36698123bc644f454ddab8303489e038129dd884 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 13:05:12 -0400 Subject: [PATCH 061/140] Adding parser generation to build file --- build.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/build.xml b/build.xml index e88584f..64383b9 100644 --- a/build.xml +++ b/build.xml @@ -9,8 +9,19 @@ + + + + + + + + + - + + + From 1b4d87a85cbb3c565483ed32e7a991eac386dd02 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 13:12:30 -0400 Subject: [PATCH 062/140] fixing parser generatin --- build.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.xml b/build.xml index 64383b9..ad9353f 100644 --- a/build.xml +++ b/build.xml @@ -10,11 +10,10 @@ - + - + - From eada1d8482c7e325b743bbd2ce81211f7a611c2e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 13:34:16 -0400 Subject: [PATCH 063/140] making executable jar --- README.md | 6 +++++- build.xml | 9 +++++++-- src/WdlMain.java | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4880cc8..2031002 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,11 @@ To build the JAR file, run: $ ant dist ``` -Which will create a file dist/Wdl-${version}.jar +Which will create a file dist/Wdl-${version}.jar as an executable JAR. To invoke from the command line: + +``` +$ java -jar dist/Wdl-0.0.1.jar examples/0.wdl ast +``` Usage ===== diff --git a/build.xml b/build.xml index ad9353f..4334417 100644 --- a/build.xml +++ b/build.xml @@ -1,4 +1,4 @@ - + @@ -25,7 +25,12 @@ - + + + + + + diff --git a/src/WdlMain.java b/src/WdlMain.java index 8b8e318..cfc5748 100644 --- a/src/WdlMain.java +++ b/src/WdlMain.java @@ -7,7 +7,7 @@ class WdlMain { public static void usage() { - System.err.println("Usage: java ParserMain <.wdl file> "); + System.err.println("Usage: <.wdl file> "); System.exit(-1); } From 7e1ce0454f5f45df14c05d8329ea7173af2aae44 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 13:39:51 -0400 Subject: [PATCH 064/140] fixing bug with graph generation --- src/CompositeTaskGraph.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CompositeTaskGraph.java b/src/CompositeTaskGraph.java index 72df21f..cc8074e 100644 --- a/src/CompositeTaskGraph.java +++ b/src/CompositeTaskGraph.java @@ -37,8 +37,10 @@ private void generate_graph(CompositeTaskScope scope) { if ( this.scope_output_map.containsKey(var) ) { CompositeTaskScope closest = closest_scope(step, this.scope_output_map.get(var)); - addVertex(closest); - addEdge(closest, step); + if ( !closest.contains(step) ) { + addVertex(closest); + addEdge(closest, step); + } } } From 4df90988cc815e0e5d04c0f5096aa0b812be2053 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 14:40:44 -0400 Subject: [PATCH 065/140] Adding some more syntax error checking --- examples/0.wdl | 4 ++-- examples/{simple.wdl => 8.wdl} | 0 examples/error0.wdl | 24 ++++++++++++++++++++++++ examples/error1.wdl | 12 ++++++++++++ src/CompositeTask.java | 22 +++++++++++++++------- src/WdlSyntaxErrorFormatter.java | 19 ++++++++++++++++--- 6 files changed, 69 insertions(+), 12 deletions(-) rename examples/{simple.wdl => 8.wdl} (100%) create mode 100644 examples/error0.wdl create mode 100644 examples/error1.wdl diff --git a/examples/0.wdl b/examples/0.wdl index 6ac7df5..c994a2a 100644 --- a/examples/0.wdl +++ b/examples/0.wdl @@ -6,12 +6,12 @@ composite_task foo { for ( item in foo ) { step btask[version=0] { - input: p0=x, p1=GLOBAL; + input: p0=x, p1=item, p2=GLOBAL; output: File("bar.txt") as y; } step ctask[version=0] { - input: p0=x, p1=y; + input: p0=x, p1=item, p2=y; output: File("quux.txt") as z; } } diff --git a/examples/simple.wdl b/examples/8.wdl similarity index 100% rename from examples/simple.wdl rename to examples/8.wdl diff --git a/examples/error0.wdl b/examples/error0.wdl new file mode 100644 index 0000000..6ac7df5 --- /dev/null +++ b/examples/error0.wdl @@ -0,0 +1,24 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=GLOBAL; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=y; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/examples/error1.wdl b/examples/error1.wdl new file mode 100644 index 0000000..e270d49 --- /dev/null +++ b/examples/error1.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + step btask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as x; + } + +} diff --git a/src/CompositeTask.java b/src/CompositeTask.java index a9d26f7..903448c 100644 --- a/src/CompositeTask.java +++ b/src/CompositeTask.java @@ -20,10 +20,12 @@ private class CompositeTaskAstVerifier { private WdlSyntaxErrorFormatter syntaxErrorFormatter; private Map variables; + private Map output_variables; CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; this.variables = new HashMap(); + this.output_variables = new HashMap(); } public Ast verify(AstNode wdl_ast) throws SyntaxError { @@ -65,14 +67,12 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { } private void set_parents(CompositeTaskScope scope) { - for ( CompositeTaskNode node : scope.getNodes() ) { node.setParent(scope); if ( node instanceof CompositeTaskScope ) { set_parents((CompositeTaskScope) node); } } - } private CompositeTaskVariable make_variable(String name, String member) { @@ -122,8 +122,8 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { name = task_name.getSourceString(); } - Set inputs = new HashSet(); - Set outputs = new HashSet(); + Set step_inputs = new HashSet(); + Set step_outputs = new HashSet(); AstList body = (AstList) step.getAttribute("body"); @@ -137,7 +137,7 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { Ast input = (Ast) input_node; Terminal parameter = (Terminal) input.getAttribute("parameter"); CompositeTaskVariable variable = ast_to_variable((Ast) input.getAttribute("value")); - inputs.add( new CompositeTaskStepInput(parameter.getSourceString(), variable) ); + step_inputs.add( new CompositeTaskStepInput(parameter.getSourceString(), variable) ); } } @@ -147,13 +147,21 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { Ast output = (Ast) output_node; Terminal filepath = (Terminal) output.getAttribute("file"); CompositeTaskVariable variable = ast_to_variable((Ast) output.getAttribute("as")); - outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); + + Terminal var_terminal = (Terminal) ((Ast) output.getAttribute("as")).getAttribute("name"); + if (this.output_variables.containsKey(variable)) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_variable(var_terminal, this.output_variables.get(variable))); + } else { + this.output_variables.put(variable, var_terminal); + } + + step_outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); } } } } - return new CompositeTaskStep(name, subtask, inputs, outputs); + return new CompositeTaskStep(name, subtask, step_inputs, step_outputs); } private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { diff --git a/src/WdlSyntaxErrorFormatter.java b/src/WdlSyntaxErrorFormatter.java index 57722dc..3cd2471 100644 --- a/src/WdlSyntaxErrorFormatter.java +++ b/src/WdlSyntaxErrorFormatter.java @@ -42,8 +42,11 @@ public String unexpected_symbol(String method, Terminal actual, List Date: Tue, 28 Aug 2012 14:50:01 -0400 Subject: [PATCH 066/140] Adding syntax error for multiple steps that output the same file --- examples/error2.wdl | 12 ++++++++++++ src/CompositeTask.java | 14 ++++++++------ src/WdlSyntaxErrorFormatter.java | 8 ++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 examples/error2.wdl diff --git a/examples/error2.wdl b/examples/error2.wdl new file mode 100644 index 0000000..5213c5b --- /dev/null +++ b/examples/error2.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as abc; + } + + step btask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("foo.txt") as xyz; + } + +} diff --git a/src/CompositeTask.java b/src/CompositeTask.java index 903448c..e787c49 100644 --- a/src/CompositeTask.java +++ b/src/CompositeTask.java @@ -21,11 +21,13 @@ private WdlSyntaxErrorFormatter syntaxErrorFormatter; private Map variables; private Map output_variables; + private Map output_files; CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; this.variables = new HashMap(); this.output_variables = new HashMap(); + this.output_files = new HashMap(); } public Ast verify(AstNode wdl_ast) throws SyntaxError { @@ -47,12 +49,6 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { throw new SyntaxError("TODO"); } - /* a) Error on two 'input' or 'output' in a Step - * b) Step names are unique in their scope (global or for) - * c) No version specified for task - * d) Two outputs have the same name - */ - AstList ctNodes = (AstList) composite_task.getAttribute("body"); CompositeTask.this.nodes = new HashSet(); @@ -155,6 +151,12 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { this.output_variables.put(variable, var_terminal); } + if (this.output_files.containsKey(filepath.getSourceString())) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_file(filepath, this.output_files.get(filepath.getSourceString()))); + } else { + this.output_files.put(filepath.getSourceString(), filepath); + } + step_outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); } } diff --git a/src/WdlSyntaxErrorFormatter.java b/src/WdlSyntaxErrorFormatter.java index 3cd2471..e3bcd27 100644 --- a/src/WdlSyntaxErrorFormatter.java +++ b/src/WdlSyntaxErrorFormatter.java @@ -67,4 +67,12 @@ public String duplicate_output_variable(Terminal duplicate, Terminal previous) { this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n"; } + public String duplicate_output_file(Terminal duplicate, Terminal previous) { + return "Two steps output to the same file: " + duplicate.getSourceString() + "\n" + + "Location: " + duplicate.getResource() + " @ line " + duplicate.getLine() + ", column " + duplicate.getColumn() + ":\n\n" + + this.code.getLine(duplicate.getLine()) + "\n" + Utility.getIndentString(duplicate.getColumn()-1) + "^\n" + + "Previous output for file was @ line " + previous.getLine() + ", column " + previous.getColumn() + ":\n\n" + + this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n"; + } + } From ddd7df06842481c8cd82a18ec231a3040dcf15f4 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 28 Aug 2012 15:26:12 -0400 Subject: [PATCH 067/140] More syntax error support --- examples/error3.wdl | 12 ++++++++++++ src/CompositeTask.java | 42 ++++++++++++++++++++++++++++++++-------- src/WdlSyntaxErrorFormatter.java | 16 +++++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 examples/error3.wdl diff --git a/examples/error3.wdl b/examples/error3.wdl new file mode 100644 index 0000000..5674ce3 --- /dev/null +++ b/examples/error3.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as abc; + } + + step atask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("bar.txt") as xyz; + } + +} diff --git a/src/CompositeTask.java b/src/CompositeTask.java index e787c49..a05c9ed 100644 --- a/src/CompositeTask.java +++ b/src/CompositeTask.java @@ -22,12 +22,14 @@ private Map variables; private Map output_variables; private Map output_files; + private Map step_names; CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; this.variables = new HashMap(); this.output_variables = new HashMap(); this.output_files = new HashMap(); + this.step_names = new HashMap(); } public Ast verify(AstNode wdl_ast) throws SyntaxError { @@ -111,13 +113,19 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { task_version.getSourceString() ); - String name; + Terminal name_terminal; if ( step.getAttribute("name") != null ) { - name = ((Terminal) step.getAttribute("name")).getSourceString(); + name_terminal = (Terminal) step.getAttribute("name"); } else { - name = task_name.getSourceString(); + name_terminal = task_name; } + String name = name_terminal.getSourceString(); + if ( this.step_names.containsKey(name) ) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_step_names(name_terminal, this.step_names.get(name))); + } + this.step_names.put(name, name_terminal); + Set step_inputs = new HashSet(); Set step_outputs = new HashSet(); @@ -169,14 +177,32 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { Set nodes = new HashSet(); - for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { - nodes.add( verify((Ast) for_sub_node) ); - } - String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); + CompositeTaskVariable collection_var = make_variable(collection, null); + CompositeTaskVariable item_var = make_variable(item, null); + + for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { + CompositeTaskNode sub_node = verify((Ast) for_sub_node); + + if ( sub_node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) sub_node; + boolean found = false; + for ( CompositeTaskStepInput input : step.getInputs() ) { + if (input.getVariable().equals(item_var)) { + found = true; + } + } + + if ( !found ) { + throw new SyntaxError(this.syntaxErrorFormatter.step_doesnt_use_loop_iterator((Terminal) for_node_ast.getAttribute("item"), this.step_names.get(step.getName()))); + } + } + + nodes.add(sub_node); + } - return new CompositeTaskForLoop(make_variable(collection, null), make_variable(item, null), nodes); + return new CompositeTaskForLoop(collection_var, item_var, nodes); } private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { diff --git a/src/WdlSyntaxErrorFormatter.java b/src/WdlSyntaxErrorFormatter.java index e3bcd27..59404c5 100644 --- a/src/WdlSyntaxErrorFormatter.java +++ b/src/WdlSyntaxErrorFormatter.java @@ -75,4 +75,20 @@ public String duplicate_output_file(Terminal duplicate, Terminal previous) { this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n"; } + public String duplicate_step_names(Terminal duplicate, Terminal previous) { + return "Two steps have the same name: " + duplicate.getSourceString() + "\n" + + "Location: " + duplicate.getResource() + " @ line " + duplicate.getLine() + ", column " + duplicate.getColumn() + ":\n\n" + + this.code.getLine(duplicate.getLine()) + "\n" + Utility.getIndentString(duplicate.getColumn()-1) + "^\n" + + "Previous step was defined @ line " + previous.getLine() + ", column " + previous.getColumn() + ":\n\n" + + this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n"; + } + + public String step_doesnt_use_loop_iterator(Terminal loop_iterator, Terminal step_name) { + return "Step '" + step_name.getSourceString() + "' inside for loop doesn't use loop iterator: " + loop_iterator.getSourceString() + "\n" + + "Location: " + step_name.getResource() + " @ line " + step_name.getLine() + ", column " + step_name.getColumn() + ":\n\n" + + this.code.getLine(step_name.getLine()) + "\n" + Utility.getIndentString(step_name.getColumn()-1) + "^\n" + + "Loop iterator is declared @ line " + loop_iterator.getLine() + ", column " + loop_iterator.getColumn() + ":\n\n" + + this.code.getLine(loop_iterator.getLine()) + "\n" + Utility.getIndentString(loop_iterator.getColumn()-1) + "^\n"; + } + } From 97022d2a2e9754948d108b756b6ac6edd04112d7 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 29 Aug 2012 10:04:37 -0300 Subject: [PATCH 068/140] Update README.md --- README.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2031002..d2fd489 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ There are two example .wdl files in the examples/ directory: * MutSig.wdl * CopyNumberQC.wdl -From Java code, the main interface is the CompositeTask, which can be used in this example to acquire the name of each task: +From Java code, the main interface is the CompositeTask, which can be used in this example to print out the immediate children nodes of this composite task: ```java CompositeTask ct = new CompositeTask(new File(args[0])); @@ -35,11 +35,6 @@ for ( CompositeTaskNode entry : ct.getNodes() ) { } ``` -Compiling is relatively straightforward: -``` -$ javac *.java -``` - The data file we'll use is: ``` @@ -66,7 +61,7 @@ composite_task test { Get the abstract syntax tree: ``` -$ java WdlMain examples/7.wdl ast +$ java -jar dist/Wdl-0.0.1.jar examples/7.wdl ast (CompositeTask: body=[ (Step: @@ -189,7 +184,7 @@ $ java WdlMain examples/7.wdl ast Get a view of the graph ``` -$ java WdlMain examples/7.wdl graph +$ java -jar dist/Wdl-0.0.1.jar examples/7.wdl graph VERTICIES --------- [Step: name=s1] From 8ffd50c8c378bc486d99817be422727d41a32f6f Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 29 Aug 2012 10:07:11 -0300 Subject: [PATCH 069/140] Update README.md --- README.md | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d2fd489..e8046aa 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,6 @@ $ java -jar dist/Wdl-0.0.1.jar examples/0.wdl ast Usage ===== -There are two example .wdl files in the examples/ directory: - -* MutSig.wdl -* CopyNumberQC.wdl - From Java code, the main interface is the CompositeTask, which can be used in this example to print out the immediate children nodes of this composite task: ```java @@ -38,6 +33,7 @@ for ( CompositeTaskNode entry : ct.getNodes() ) { The data file we'll use is: ``` +$ cat examples/7.wdl composite_task test { step s0[version=0] { output: File("abc") as foo; @@ -202,47 +198,47 @@ VERTICIES EDGES ----- [Edge - from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] - to: [Variable: name=I] -] -[Edge - from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] - to: [Step: name=s2] -] -[Edge - from: [Variable: name=J] - to: [Step: name=s1] + from: [Step: name=s1] + to: [Variable: name=bar] ] [Edge from: [Variable: name=L] to: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] ] [Edge + from: [Variable: name=bar] + to: [Step: name=s2] +] +[Edge from: [Variable: name=foo] to: [Step: name=s1] ] [Edge - from: [Variable: name=I] - to: [Step: name=s1] + from: [Step: name=s0] + to: [Variable: name=foo] ] [Edge from: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] to: [Variable: name=J] ] [Edge - from: [Step: name=s0] - to: [Variable: name=foo] + from: [Variable: name=J] + to: [Step: name=s1] ] [Edge - from: [Step: name=s1] - to: [Variable: name=bar] + from: [Variable: name=M] + to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] ] [Edge - from: [Variable: name=bar] + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] to: [Step: name=s2] ] [Edge - from: [Variable: name=M] - to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + from: [Variable: name=I] + to: [Step: name=s1] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Variable: name=I] ] ``` From 28b2bc68fe359d34423241bd7cc19bbb6a8275ba Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 30 Aug 2012 14:22:31 -0400 Subject: [PATCH 070/140] adding parser generation to the ant build script --- build.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.xml b/build.xml index 4334417..5e5212f 100644 --- a/build.xml +++ b/build.xml @@ -10,6 +10,12 @@ + + + + + + From 96725f4589ec7ff0a877e12286791dc206525a4a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 31 Aug 2012 12:44:22 -0400 Subject: [PATCH 071/140] reorganizing code and making new package org.broadinstitute.compositetask --- build.xml | 10 +- src/AstTransform.java | 1 - src/CompositeTaskScope.java | 6 - src/CompositeTaskToDotCompiler.java | 5 - src/CompositeTaskVertex.java | 1 - src/WdlColorTheme.java | 5 - src/WdlSourceCodeNormalizer.java | 5 - src/WdlTerminalColorizer.java | 3 - .../broadinstitute/compositetask}/Ast.java | 2 + .../broadinstitute/compositetask}/AstList.java | 2 + .../broadinstitute/compositetask}/AstNode.java | 2 + .../broadinstitute/compositetask/AstTransform.java | 3 + .../compositetask}/AstTransformNodeCreator.java | 2 + .../compositetask}/AstTransformSubstitution.java | 2 + .../compositetask}/CompositeTask.java | 4 +- .../compositetask}/CompositeTaskEdge.java | 4 +- .../compositetask}/CompositeTaskEdgeFactory.java | 4 +- .../compositetask}/CompositeTaskForLoop.java | 4 +- .../compositetask}/CompositeTaskGraph.java | 4 +- .../compositetask}/CompositeTaskNode.java | 4 +- .../compositetask/CompositeTaskScope.java | 8 + .../compositetask}/CompositeTaskStep.java | 4 +- .../compositetask}/CompositeTaskStepInput.java | 4 +- .../compositetask}/CompositeTaskStepOutput.java | 4 +- .../compositetask}/CompositeTaskSubTask.java | 4 +- .../compositetask/CompositeTaskToDotCompiler.java | 7 + .../compositetask}/CompositeTaskVariable.java | 4 +- .../compositetask/CompositeTaskVertex.java | 3 + .../compositetask}/ExpressionParser.java | 2 + .../broadinstitute/compositetask}/Lexer.java | 2 + .../broadinstitute/compositetask}/NonTerminal.java | 2 + .../broadinstitute/compositetask}/ParseTree.java | 2 + .../compositetask}/ParseTreeNode.java | 2 + .../broadinstitute/compositetask}/Parser.java | 2 + .../broadinstitute/compositetask}/SourceCode.java | 2 + .../broadinstitute/compositetask}/SyntaxError.java | 2 + .../compositetask}/SyntaxErrorFormatter.java | 2 + .../broadinstitute/compositetask}/Terminal.java | 2 + .../compositetask}/TerminalIdentifier.java | 2 + .../broadinstitute/compositetask}/TerminalMap.java | 2 + .../broadinstitute/compositetask}/TokenStream.java | 2 + .../broadinstitute/compositetask}/Utility.java | 2 + .../compositetask}/WdlAnsiColorizer.java | 4 +- .../compositetask/WdlColorTheme.java | 7 + .../compositetask}/WdlHtmlColorizer.java | 4 +- .../broadinstitute/compositetask}/WdlMain.java | 4 +- .../broadinstitute/compositetask}/WdlParser.java | 1325 ++++++++++---------- .../compositetask}/WdlSourceCode.java | 4 +- .../compositetask}/WdlSourceCodeFormatter.java | 4 +- .../compositetask/WdlSourceCodeNormalizer.java | 7 + .../compositetask}/WdlSyntaxErrorFormatter.java | 4 +- .../compositetask/WdlTerminalColorizer.java | 5 + 52 files changed, 798 insertions(+), 709 deletions(-) delete mode 100644 src/AstTransform.java delete mode 100644 src/CompositeTaskScope.java delete mode 100644 src/CompositeTaskToDotCompiler.java delete mode 100644 src/CompositeTaskVertex.java delete mode 100644 src/WdlColorTheme.java delete mode 100644 src/WdlSourceCodeNormalizer.java delete mode 100644 src/WdlTerminalColorizer.java rename src/{ => org/broadinstitute/compositetask}/Ast.java (97%) rename src/{ => org/broadinstitute/compositetask}/AstList.java (93%) rename src/{ => org/broadinstitute/compositetask}/AstNode.java (74%) create mode 100644 src/org/broadinstitute/compositetask/AstTransform.java rename src/{ => org/broadinstitute/compositetask}/AstTransformNodeCreator.java (95%) rename src/{ => org/broadinstitute/compositetask}/AstTransformSubstitution.java (87%) rename src/{ => org/broadinstitute/compositetask}/CompositeTask.java (99%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskEdge.java (88%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskEdgeFactory.java (60%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskForLoop.java (92%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskGraph.java (98%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskNode.java (59%) create mode 100644 src/org/broadinstitute/compositetask/CompositeTaskScope.java rename src/{ => org/broadinstitute/compositetask}/CompositeTaskStep.java (90%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskStepInput.java (89%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskStepOutput.java (89%) rename src/{ => org/broadinstitute/compositetask}/CompositeTaskSubTask.java (86%) create mode 100644 src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java rename src/{ => org/broadinstitute/compositetask}/CompositeTaskVariable.java (88%) create mode 100644 src/org/broadinstitute/compositetask/CompositeTaskVertex.java rename src/{ => org/broadinstitute/compositetask}/ExpressionParser.java (72%) rename src/{ => org/broadinstitute/compositetask}/Lexer.java (99%) rename src/{ => org/broadinstitute/compositetask}/NonTerminal.java (87%) rename src/{ => org/broadinstitute/compositetask}/ParseTree.java (99%) rename src/{ => org/broadinstitute/compositetask}/ParseTreeNode.java (79%) rename src/{ => org/broadinstitute/compositetask}/Parser.java (72%) rename src/{ => org/broadinstitute/compositetask}/SourceCode.java (85%) rename src/{ => org/broadinstitute/compositetask}/SyntaxError.java (69%) rename src/{ => org/broadinstitute/compositetask}/SyntaxErrorFormatter.java (95%) rename src/{ => org/broadinstitute/compositetask}/Terminal.java (97%) rename src/{ => org/broadinstitute/compositetask}/TerminalIdentifier.java (64%) rename src/{ => org/broadinstitute/compositetask}/TerminalMap.java (75%) rename src/{ => org/broadinstitute/compositetask}/TokenStream.java (97%) rename src/{ => org/broadinstitute/compositetask}/Utility.java (98%) rename src/{ => org/broadinstitute/compositetask}/WdlAnsiColorizer.java (53%) create mode 100644 src/org/broadinstitute/compositetask/WdlColorTheme.java rename src/{ => org/broadinstitute/compositetask}/WdlHtmlColorizer.java (52%) rename src/{ => org/broadinstitute/compositetask}/WdlMain.java (96%) rename src/{ => org/broadinstitute/compositetask}/WdlParser.java (84%) rename src/{ => org/broadinstitute/compositetask}/WdlSourceCode.java (96%) rename src/{ => org/broadinstitute/compositetask}/WdlSourceCodeFormatter.java (86%) create mode 100644 src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java rename src/{ => org/broadinstitute/compositetask}/WdlSyntaxErrorFormatter.java (97%) create mode 100644 src/org/broadinstitute/compositetask/WdlTerminalColorizer.java diff --git a/build.xml b/build.xml index 5e5212f..d854993 100644 --- a/build.xml +++ b/build.xml @@ -14,12 +14,14 @@ - + - + - + + + @@ -33,7 +35,7 @@ - + diff --git a/src/AstTransform.java b/src/AstTransform.java deleted file mode 100644 index f01ae0c..0000000 --- a/src/AstTransform.java +++ /dev/null @@ -1 +0,0 @@ -interface AstTransform {} diff --git a/src/CompositeTaskScope.java b/src/CompositeTaskScope.java deleted file mode 100644 index 6c9ebe7..0000000 --- a/src/CompositeTaskScope.java +++ /dev/null @@ -1,6 +0,0 @@ -import java.util.Set; - -interface CompositeTaskScope extends CompositeTaskNode, CompositeTaskVertex { - public Set getNodes(); - public boolean contains(CompositeTaskNode node); -} diff --git a/src/CompositeTaskToDotCompiler.java b/src/CompositeTaskToDotCompiler.java deleted file mode 100644 index eb29fe9..0000000 --- a/src/CompositeTaskToDotCompiler.java +++ /dev/null @@ -1,5 +0,0 @@ -class CompositeTaskToDotCompiler { - public String compile(CompositeTask task) { - return null; - } -} diff --git a/src/CompositeTaskVertex.java b/src/CompositeTaskVertex.java deleted file mode 100644 index 4d07333..0000000 --- a/src/CompositeTaskVertex.java +++ /dev/null @@ -1 +0,0 @@ -interface CompositeTaskVertex {} diff --git a/src/WdlColorTheme.java b/src/WdlColorTheme.java deleted file mode 100644 index 7d16983..0000000 --- a/src/WdlColorTheme.java +++ /dev/null @@ -1,5 +0,0 @@ -import java.awt.Color; - -interface WdlColorTheme { - Color getColor(Terminal terminal); -} diff --git a/src/WdlSourceCodeNormalizer.java b/src/WdlSourceCodeNormalizer.java deleted file mode 100644 index 45400ea..0000000 --- a/src/WdlSourceCodeNormalizer.java +++ /dev/null @@ -1,5 +0,0 @@ -class WdlSourceCodeNormalizer { - ParseTree format(ParseTree tree) { - return null; - } -} diff --git a/src/WdlTerminalColorizer.java b/src/WdlTerminalColorizer.java deleted file mode 100644 index d7333c6..0000000 --- a/src/WdlTerminalColorizer.java +++ /dev/null @@ -1,3 +0,0 @@ -interface WdlTerminalColorizer { - String colorize(Terminal terminal); -} diff --git a/src/Ast.java b/src/org/broadinstitute/compositetask/Ast.java similarity index 97% rename from src/Ast.java rename to src/org/broadinstitute/compositetask/Ast.java index 7b020df..451f022 100644 --- a/src/Ast.java +++ b/src/org/broadinstitute/compositetask/Ast.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.Map; import java.util.LinkedList; import java.util.Formatter; diff --git a/src/AstList.java b/src/org/broadinstitute/compositetask/AstList.java similarity index 93% rename from src/AstList.java rename to src/org/broadinstitute/compositetask/AstList.java index 220d2e1..5ebfc6f 100644 --- a/src/AstList.java +++ b/src/org/broadinstitute/compositetask/AstList.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.ArrayList; class AstList extends ArrayList implements AstNode { public String toString() { diff --git a/src/AstNode.java b/src/org/broadinstitute/compositetask/AstNode.java similarity index 74% rename from src/AstNode.java rename to src/org/broadinstitute/compositetask/AstNode.java index 5e30462..ce7930b 100644 --- a/src/AstNode.java +++ b/src/org/broadinstitute/compositetask/AstNode.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; interface AstNode { public String toString(); public String toPrettyString(); diff --git a/src/org/broadinstitute/compositetask/AstTransform.java b/src/org/broadinstitute/compositetask/AstTransform.java new file mode 100644 index 0000000..e75e489 --- /dev/null +++ b/src/org/broadinstitute/compositetask/AstTransform.java @@ -0,0 +1,3 @@ + +package org.broadinstitute.compositetask; +interface AstTransform {} diff --git a/src/AstTransformNodeCreator.java b/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java similarity index 95% rename from src/AstTransformNodeCreator.java rename to src/org/broadinstitute/compositetask/AstTransformNodeCreator.java index f708c21..19c357b 100644 --- a/src/AstTransformNodeCreator.java +++ b/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.LinkedList; import java.util.Map; import java.util.LinkedHashMap; diff --git a/src/AstTransformSubstitution.java b/src/org/broadinstitute/compositetask/AstTransformSubstitution.java similarity index 87% rename from src/AstTransformSubstitution.java rename to src/org/broadinstitute/compositetask/AstTransformSubstitution.java index 404b7bd..32a8a2d 100644 --- a/src/AstTransformSubstitution.java +++ b/src/org/broadinstitute/compositetask/AstTransformSubstitution.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; class AstTransformSubstitution implements AstTransform { private int index; AstTransformSubstitution(int index) { diff --git a/src/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java similarity index 99% rename from src/CompositeTask.java rename to src/org/broadinstitute/compositetask/CompositeTask.java index a05c9ed..d6ee03d 100644 --- a/src/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -1,3 +1,5 @@ +package org.broadinstitute.compositetask; + import java.io.File; import java.io.IOException; import java.util.List; @@ -8,7 +10,7 @@ import java.util.Iterator; import org.jgrapht.DirectedGraph; -class CompositeTask implements CompositeTaskScope { +public class CompositeTask implements CompositeTaskScope { private ParseTree parse_tree; private Ast ast; diff --git a/src/CompositeTaskEdge.java b/src/org/broadinstitute/compositetask/CompositeTaskEdge.java similarity index 88% rename from src/CompositeTaskEdge.java rename to src/org/broadinstitute/compositetask/CompositeTaskEdge.java index 31829ec..818b1a5 100644 --- a/src/CompositeTaskEdge.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskEdge.java @@ -1,4 +1,6 @@ -class CompositeTaskEdge { +package org.broadinstitute.compositetask; + +public class CompositeTaskEdge { private CompositeTaskVertex start; private CompositeTaskVertex end; diff --git a/src/CompositeTaskEdgeFactory.java b/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java similarity index 60% rename from src/CompositeTaskEdgeFactory.java rename to src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java index 06379fe..79bf5d2 100644 --- a/src/CompositeTaskEdgeFactory.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import org.jgrapht.EdgeFactory; -class CompositeTaskEdgeFactory implements EdgeFactory +public class CompositeTaskEdgeFactory implements EdgeFactory { public CompositeTaskEdge createEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { return new CompositeTaskEdge(sourceVertex, targetVertex); diff --git a/src/CompositeTaskForLoop.java b/src/org/broadinstitute/compositetask/CompositeTaskForLoop.java similarity index 92% rename from src/CompositeTaskForLoop.java rename to src/org/broadinstitute/compositetask/CompositeTaskForLoop.java index f3c5a33..9efbcb1 100644 --- a/src/CompositeTaskForLoop.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskForLoop.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskForLoop implements CompositeTaskScope { +public class CompositeTaskForLoop implements CompositeTaskScope { private CompositeTaskVariable collection; private CompositeTaskVariable var; private Set nodes; diff --git a/src/CompositeTaskGraph.java b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java similarity index 98% rename from src/CompositeTaskGraph.java rename to src/org/broadinstitute/compositetask/CompositeTaskGraph.java index cc8074e..00476e0 100644 --- a/src/CompositeTaskGraph.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java @@ -1,3 +1,5 @@ +package org.broadinstitute.compositetask; + import java.util.Set; import java.util.Collection; import java.util.Map; @@ -8,7 +10,7 @@ import org.jgrapht.DirectedGraph; import org.jgrapht.EdgeFactory; -class CompositeTaskGraph implements DirectedGraph +public class CompositeTaskGraph implements DirectedGraph { private Map> scope_output_map; private Set verticies; diff --git a/src/CompositeTaskNode.java b/src/org/broadinstitute/compositetask/CompositeTaskNode.java similarity index 59% rename from src/CompositeTaskNode.java rename to src/org/broadinstitute/compositetask/CompositeTaskNode.java index 1d22c20..baeb1fb 100644 --- a/src/CompositeTaskNode.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskNode.java @@ -1,4 +1,6 @@ -interface CompositeTaskNode { +package org.broadinstitute.compositetask; + +public interface CompositeTaskNode { public Ast getAst(); public void setParent(CompositeTaskScope parent); public CompositeTaskScope getParent(); diff --git a/src/org/broadinstitute/compositetask/CompositeTaskScope.java b/src/org/broadinstitute/compositetask/CompositeTaskScope.java new file mode 100644 index 0000000..53bb245 --- /dev/null +++ b/src/org/broadinstitute/compositetask/CompositeTaskScope.java @@ -0,0 +1,8 @@ +package org.broadinstitute.compositetask; + +import java.util.Set; + +public interface CompositeTaskScope extends CompositeTaskNode, CompositeTaskVertex { + public Set getNodes(); + public boolean contains(CompositeTaskNode node); +} diff --git a/src/CompositeTaskStep.java b/src/org/broadinstitute/compositetask/CompositeTaskStep.java similarity index 90% rename from src/CompositeTaskStep.java rename to src/org/broadinstitute/compositetask/CompositeTaskStep.java index ad8b280..8804702 100644 --- a/src/CompositeTaskStep.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskStep.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskStep implements CompositeTaskNode, CompositeTaskVertex { +public class CompositeTaskStep implements CompositeTaskNode, CompositeTaskVertex { private CompositeTaskSubTask task; private String name; private Set inputs; diff --git a/src/CompositeTaskStepInput.java b/src/org/broadinstitute/compositetask/CompositeTaskStepInput.java similarity index 89% rename from src/CompositeTaskStepInput.java rename to src/org/broadinstitute/compositetask/CompositeTaskStepInput.java index d2468f4..5a3e0b0 100644 --- a/src/CompositeTaskStepInput.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskStepInput.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskStepInput { +public class CompositeTaskStepInput { private String parameter; private CompositeTaskVariable variable; diff --git a/src/CompositeTaskStepOutput.java b/src/org/broadinstitute/compositetask/CompositeTaskStepOutput.java similarity index 89% rename from src/CompositeTaskStepOutput.java rename to src/org/broadinstitute/compositetask/CompositeTaskStepOutput.java index 0455280..43bafc6 100644 --- a/src/CompositeTaskStepOutput.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskStepOutput.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskStepOutput { +public class CompositeTaskStepOutput { private String type; private String path; private CompositeTaskVariable variable; diff --git a/src/CompositeTaskSubTask.java b/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java similarity index 86% rename from src/CompositeTaskSubTask.java rename to src/org/broadinstitute/compositetask/CompositeTaskSubTask.java index 88f37b6..76a1be5 100644 --- a/src/CompositeTaskSubTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskSubTask { +public class CompositeTaskSubTask { private String name; private String version; diff --git a/src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java b/src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java new file mode 100644 index 0000000..182fbdf --- /dev/null +++ b/src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java @@ -0,0 +1,7 @@ +package org.broadinstitute.compositetask; + +public class CompositeTaskToDotCompiler { + public String compile(CompositeTask task) { + return null; + } +} diff --git a/src/CompositeTaskVariable.java b/src/org/broadinstitute/compositetask/CompositeTaskVariable.java similarity index 88% rename from src/CompositeTaskVariable.java rename to src/org/broadinstitute/compositetask/CompositeTaskVariable.java index cf5edad..c40e442 100644 --- a/src/CompositeTaskVariable.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskVariable.java @@ -1,6 +1,8 @@ +package org.broadinstitute.compositetask; + import java.util.Set; -class CompositeTaskVariable implements CompositeTaskVertex { +public class CompositeTaskVariable implements CompositeTaskVertex { private String name; private String member; diff --git a/src/org/broadinstitute/compositetask/CompositeTaskVertex.java b/src/org/broadinstitute/compositetask/CompositeTaskVertex.java new file mode 100644 index 0000000..e463b91 --- /dev/null +++ b/src/org/broadinstitute/compositetask/CompositeTaskVertex.java @@ -0,0 +1,3 @@ +package org.broadinstitute.compositetask; + +public interface CompositeTaskVertex {} diff --git a/src/ExpressionParser.java b/src/org/broadinstitute/compositetask/ExpressionParser.java similarity index 72% rename from src/ExpressionParser.java rename to src/org/broadinstitute/compositetask/ExpressionParser.java index 7dfbd91..a4f2b6d 100644 --- a/src/ExpressionParser.java +++ b/src/org/broadinstitute/compositetask/ExpressionParser.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; interface ExpressionParser extends Parser { ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; } diff --git a/src/Lexer.java b/src/org/broadinstitute/compositetask/Lexer.java similarity index 99% rename from src/Lexer.java rename to src/org/broadinstitute/compositetask/Lexer.java index 5b59b2d..c31910f 100644 --- a/src/Lexer.java +++ b/src/org/broadinstitute/compositetask/Lexer.java @@ -1,3 +1,5 @@ +package org.broadinstitute.compositetask; + import java.util.regex.*; import java.util.ArrayList; import java.util.List; diff --git a/src/NonTerminal.java b/src/org/broadinstitute/compositetask/NonTerminal.java similarity index 87% rename from src/NonTerminal.java rename to src/org/broadinstitute/compositetask/NonTerminal.java index b0b17e2..08a45ef 100644 --- a/src/NonTerminal.java +++ b/src/org/broadinstitute/compositetask/NonTerminal.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; class NonTerminal { private int id; private String string; diff --git a/src/ParseTree.java b/src/org/broadinstitute/compositetask/ParseTree.java similarity index 99% rename from src/ParseTree.java rename to src/org/broadinstitute/compositetask/ParseTree.java index b7a7bda..8270387 100644 --- a/src/ParseTree.java +++ b/src/org/broadinstitute/compositetask/ParseTree.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.ArrayList; import java.util.Map; import java.util.List; diff --git a/src/ParseTreeNode.java b/src/org/broadinstitute/compositetask/ParseTreeNode.java similarity index 79% rename from src/ParseTreeNode.java rename to src/org/broadinstitute/compositetask/ParseTreeNode.java index 9d6eb97..c3f045a 100644 --- a/src/ParseTreeNode.java +++ b/src/org/broadinstitute/compositetask/ParseTreeNode.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; public interface ParseTreeNode { public AstNode toAst(); public String toString(); diff --git a/src/Parser.java b/src/org/broadinstitute/compositetask/Parser.java similarity index 72% rename from src/Parser.java rename to src/org/broadinstitute/compositetask/Parser.java index 8746412..d9fcf1f 100644 --- a/src/Parser.java +++ b/src/org/broadinstitute/compositetask/Parser.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; interface Parser { ParseTree parse(TokenStream tokens) throws SyntaxError; TerminalMap getTerminalMap(); diff --git a/src/SourceCode.java b/src/org/broadinstitute/compositetask/SourceCode.java similarity index 85% rename from src/SourceCode.java rename to src/org/broadinstitute/compositetask/SourceCode.java index 45d4c26..6335edc 100644 --- a/src/SourceCode.java +++ b/src/org/broadinstitute/compositetask/SourceCode.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.List; interface SourceCode { public void advance(int amount); diff --git a/src/SyntaxError.java b/src/org/broadinstitute/compositetask/SyntaxError.java similarity index 69% rename from src/SyntaxError.java rename to src/org/broadinstitute/compositetask/SyntaxError.java index 9ea950e..90e0098 100644 --- a/src/SyntaxError.java +++ b/src/org/broadinstitute/compositetask/SyntaxError.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; class SyntaxError extends Exception { SyntaxError(String message) { super(message); diff --git a/src/SyntaxErrorFormatter.java b/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java similarity index 95% rename from src/SyntaxErrorFormatter.java rename to src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java index caf9db6..5822b13 100644 --- a/src/SyntaxErrorFormatter.java +++ b/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.List; interface SyntaxErrorFormatter { /* Called when the parser runs out of tokens but isn't finished parsing. */ diff --git a/src/Terminal.java b/src/org/broadinstitute/compositetask/Terminal.java similarity index 97% rename from src/Terminal.java rename to src/org/broadinstitute/compositetask/Terminal.java index f187065..1fa5987 100644 --- a/src/Terminal.java +++ b/src/org/broadinstitute/compositetask/Terminal.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.Formatter; import java.util.Locale; class Terminal implements AstNode, ParseTreeNode diff --git a/src/TerminalIdentifier.java b/src/org/broadinstitute/compositetask/TerminalIdentifier.java similarity index 64% rename from src/TerminalIdentifier.java rename to src/org/broadinstitute/compositetask/TerminalIdentifier.java index 453b513..4039353 100644 --- a/src/TerminalIdentifier.java +++ b/src/org/broadinstitute/compositetask/TerminalIdentifier.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; interface TerminalIdentifier { public int id(); public String string(); diff --git a/src/TerminalMap.java b/src/org/broadinstitute/compositetask/TerminalMap.java similarity index 75% rename from src/TerminalMap.java rename to src/org/broadinstitute/compositetask/TerminalMap.java index f198d39..1ea4329 100644 --- a/src/TerminalMap.java +++ b/src/org/broadinstitute/compositetask/TerminalMap.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; interface TerminalMap { int get(String string); String get(int id); diff --git a/src/TokenStream.java b/src/org/broadinstitute/compositetask/TokenStream.java similarity index 97% rename from src/TokenStream.java rename to src/org/broadinstitute/compositetask/TokenStream.java index cd7cc95..adae466 100644 --- a/src/TokenStream.java +++ b/src/org/broadinstitute/compositetask/TokenStream.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.ArrayList; import java.util.List; import java.util.Formatter; diff --git a/src/Utility.java b/src/org/broadinstitute/compositetask/Utility.java similarity index 98% rename from src/Utility.java rename to src/org/broadinstitute/compositetask/Utility.java index 60bbde1..04b8871 100644 --- a/src/Utility.java +++ b/src/org/broadinstitute/compositetask/Utility.java @@ -1,3 +1,5 @@ + +package org.broadinstitute.compositetask; import java.util.Collection; import java.util.Iterator; import java.io.IOException; diff --git a/src/WdlAnsiColorizer.java b/src/org/broadinstitute/compositetask/WdlAnsiColorizer.java similarity index 53% rename from src/WdlAnsiColorizer.java rename to src/org/broadinstitute/compositetask/WdlAnsiColorizer.java index 03dbe9d..6fcfbb5 100644 --- a/src/WdlAnsiColorizer.java +++ b/src/org/broadinstitute/compositetask/WdlAnsiColorizer.java @@ -1,4 +1,6 @@ -class WdlAnsiColorizer implements WdlTerminalColorizer { +package org.broadinstitute.compositetask; + +public class WdlAnsiColorizer implements WdlTerminalColorizer { WdlAnsiColorizer(WdlColorTheme theme) { } diff --git a/src/org/broadinstitute/compositetask/WdlColorTheme.java b/src/org/broadinstitute/compositetask/WdlColorTheme.java new file mode 100644 index 0000000..7651276 --- /dev/null +++ b/src/org/broadinstitute/compositetask/WdlColorTheme.java @@ -0,0 +1,7 @@ +package org.broadinstitute.compositetask; + +import java.awt.Color; + +public interface WdlColorTheme { + Color getColor(Terminal terminal); +} diff --git a/src/WdlHtmlColorizer.java b/src/org/broadinstitute/compositetask/WdlHtmlColorizer.java similarity index 52% rename from src/WdlHtmlColorizer.java rename to src/org/broadinstitute/compositetask/WdlHtmlColorizer.java index ed32849..4c1f874 100644 --- a/src/WdlHtmlColorizer.java +++ b/src/org/broadinstitute/compositetask/WdlHtmlColorizer.java @@ -1,4 +1,6 @@ -class WdlHtmlColorizer implements WdlTerminalColorizer { +package org.broadinstitute.compositetask; + +public class WdlHtmlColorizer implements WdlTerminalColorizer { WdlHtmlColorizer(WdlColorTheme theme) { } diff --git a/src/WdlMain.java b/src/org/broadinstitute/compositetask/WdlMain.java similarity index 96% rename from src/WdlMain.java rename to src/org/broadinstitute/compositetask/WdlMain.java index cfc5748..c8d7190 100644 --- a/src/WdlMain.java +++ b/src/org/broadinstitute/compositetask/WdlMain.java @@ -1,10 +1,12 @@ +package org.broadinstitute.compositetask; + import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; -class WdlMain { +public class WdlMain { public static void usage() { System.err.println("Usage: <.wdl file> "); diff --git a/src/WdlParser.java b/src/org/broadinstitute/compositetask/WdlParser.java similarity index 84% rename from src/WdlParser.java rename to src/org/broadinstitute/compositetask/WdlParser.java index 00e9ae5..7a33b0d 100644 --- a/src/WdlParser.java +++ b/src/org/broadinstitute/compositetask/WdlParser.java @@ -1,4 +1,5 @@ +package org.broadinstitute.compositetask; import java.util.*; import java.util.HashMap; import java.util.LinkedHashMap; @@ -13,59 +14,59 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, 14, 11, -1 }, - { -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1 }, + { -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 6, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 32, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 20, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1 }, + { -1, -1, 42, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, 42, -1 }, + { -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 38, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, 36, -1, -1, -1, 33, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, 33, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1 }, - { -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1 }, - { -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 4, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 44, -1, -1, -1, -1, -1, -1, 44, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 19, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 43, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 18, 18, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 31, -1, 3, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, 18, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1 }, + { -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, 22, -1, -1, -1 }, + { -1, -1, -1, 31, -1, 11, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_RPAREN(0, "rparen"), - TERMINAL_OUTPUT(1, "output"), - TERMINAL_FILE(2, "file"), - TERMINAL_LSQUARE(3, "lsquare"), - TERMINAL_AS(4, "as"), - TERMINAL_COMPOSITE_TASK(5, "composite_task"), - TERMINAL_STEP(6, "step"), - TERMINAL_IDENTIFIER(7, "identifier"), - TERMINAL_INPUT(8, "input"), - TERMINAL_STRING(9, "string"), - TERMINAL_RBRACE(10, "rbrace"), - TERMINAL_IN(11, "in"), - TERMINAL_SEMI(12, "semi"), - TERMINAL_NUMBER(13, "number"), - TERMINAL_RSQUARE(14, "rsquare"), - TERMINAL_COLON(15, "colon"), - TERMINAL_ASSIGN(16, "assign"), - TERMINAL_FOR(17, "for"), - TERMINAL_LPAREN(18, "lparen"), - TERMINAL_DOT(19, "dot"), - TERMINAL_COMMA(20, "comma"), - TERMINAL_LBRACE(21, "lbrace"); + TERMINAL_FILE(0, "file"), + TERMINAL_COLON(1, "colon"), + TERMINAL_COMPOSITE_TASK(2, "composite_task"), + TERMINAL_IDENTIFIER(3, "identifier"), + TERMINAL_LPAREN(4, "lparen"), + TERMINAL_STRING(5, "string"), + TERMINAL_RBRACE(6, "rbrace"), + TERMINAL_LSQUARE(7, "lsquare"), + TERMINAL_SEMI(8, "semi"), + TERMINAL_RSQUARE(9, "rsquare"), + TERMINAL_NUMBER(10, "number"), + TERMINAL_LBRACE(11, "lbrace"), + TERMINAL_COMMA(12, "comma"), + TERMINAL_AS(13, "as"), + TERMINAL_INPUT(14, "input"), + TERMINAL_IN(15, "in"), + TERMINAL_DOT(16, "dot"), + TERMINAL_STEP(17, "step"), + TERMINAL_OUTPUT(18, "output"), + TERMINAL_ASSIGN(19, "assign"), + TERMINAL_FOR(20, "for"), + TERMINAL_RPAREN(21, "rparen"); private final int id; private final String string; TerminalId(int id, String string) { @@ -102,228 +103,228 @@ this.rules = new HashMap(); ArrayList list; String rule; - this.nonterminal_rules.put("wdl_entity", new ArrayList()); - this.nonterminal_rules.put("_gen10", new ArrayList()); - this.nonterminal_rules.put("step", new ArrayList()); - this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("step_input_list", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); - this.nonterminal_rules.put("_gen9", new ArrayList()); - this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("_gen2", new ArrayList()); - this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("task_attrs", new ArrayList()); - this.nonterminal_rules.put("composite_task_entity", new ArrayList()); - this.nonterminal_rules.put("step_name", new ArrayList()); - this.nonterminal_rules.put("_gen3", new ArrayList()); - this.nonterminal_rules.put("_gen4", new ArrayList()); - this.nonterminal_rules.put("step_output", new ArrayList()); - this.nonterminal_rules.put("task_identifier", new ArrayList()); - this.nonterminal_rules.put("step_attr", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); - this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("_gen1", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); - this.nonterminal_rules.put("step_output_list", new ArrayList()); - this.nonterminal_rules.put("task_attr_value", new ArrayList()); - this.nonterminal_rules.put("variable", new ArrayList()); - this.nonterminal_rules.put("_gen8", new ArrayList()); - this.nonterminal_rules.put("wdl", new ArrayList()); - this.nonterminal_rules.put("composite_task", new ArrayList()); - this.nonterminal_rules.put("_gen7", new ArrayList()); - rule = "wdl := _gen0"; - this.nonterminal_rules.get("wdl").add(rule); + this.nonterminal_rules.put("step", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("task_attr", new ArrayList()); + this.nonterminal_rules.put("_gen9", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); + this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("step_name", new ArrayList()); + this.nonterminal_rules.put("composite_task_entity", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); + this.nonterminal_rules.put("_gen8", new ArrayList()); + this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("step_input", new ArrayList()); + this.nonterminal_rules.put("_gen10", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); + this.nonterminal_rules.put("_gen3", new ArrayList()); + this.nonterminal_rules.put("task_attr_value", new ArrayList()); + this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); + this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); + rule = "_gen4 := task_attrs"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(0), rule); + rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; + this.nonterminal_rules.get("step").add(rule); + this.rules.put(new Integer(1), rule); rule = "_gen7 := 'comma' step_input _gen7"; this.nonterminal_rules.get("_gen7").add(rule); - this.rules.put(new Integer(1), rule); - rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; - this.nonterminal_rules.get("step_input").add(rule); this.rules.put(new Integer(2), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); - this.rules.put(new Integer(3), rule); - rule = "composite_task_entity := composite_task"; + rule = "composite_task_entity := step"; this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(3), rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(4), rule); - rule = "_gen7 := ε"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(5), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen5 := task_attr _gen5"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(6), rule); rule = "_gen5 := ε"; this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(7), rule); - rule = "_gen6 := ε"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "_gen9 := 'comma' step_output _gen9"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(8), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "variable := 'identifier' _gen10 -> Variable( member=$1, name=$0 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(9), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; - this.nonterminal_rules.get("task_attr").add(rule); + rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); this.rules.put(new Integer(10), rule); - rule = "_gen10 := ε"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(11), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "_gen2 := step_name"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(12), rule); - rule = "_gen4 := ε"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(13), rule); - rule = "_gen10 := variable_member"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "_gen2 := ε"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(14), rule); - rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); this.rules.put(new Integer(15), rule); - rule = "_gen3 := ε"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(16), rule); - rule = "task_attr_value := 'number'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); this.rules.put(new Integer(17), rule); - rule = "_gen1 := composite_task_entity _gen1"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(18), rule); - rule = "_gen4 := task_attrs"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "composite_task_entity := composite_task"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(19), rule); - rule = "variable := 'identifier' _gen10 -> Variable( member=$1, name=$0 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(20), rule); - rule = "_gen2 := step_name"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(21), rule); - rule = "variable_member := 'dot' 'identifier' -> $1"; - this.nonterminal_rules.get("variable_member").add(rule); + rule = "_gen3 := step_attr _gen3"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(22), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; + this.nonterminal_rules.get("step_output").add(rule); this.rules.put(new Integer(23), rule); - rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; - this.nonterminal_rules.get("step").add(rule); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(24), rule); - rule = "_gen8 := step_output _gen9"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(25), rule); - rule = "task_identifier := 'identifier' _gen4 -> Task( attributes=$1, name=$0 )"; - this.nonterminal_rules.get("task_identifier").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(26), rule); - rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); this.rules.put(new Integer(27), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "_gen7 := ε"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(28), rule); - rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; - this.nonterminal_rules.get("step_input_list").add(rule); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); this.rules.put(new Integer(29), rule); - rule = "composite_task_entity := step"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen6 := ε"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(30), rule); rule = "task_attr_value := 'identifier'"; this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(31), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "_gen6 := step_input _gen7"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(32), rule); - rule = "_gen9 := 'comma' step_output _gen9"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "_gen10 := variable_member"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(33), rule); - rule = "step_name := 'as' 'identifier' -> $1"; - this.nonterminal_rules.get("step_name").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(34), rule); - rule = "_gen2 := ε"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(35), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(36), rule); - rule = "_gen5 := task_attr _gen5"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(37), rule); - rule = "_gen6 := step_input _gen7"; - this.nonterminal_rules.get("_gen6").add(rule); - this.rules.put(new Integer(38), rule); - rule = "_gen8 := ε"; + rule = "_gen8 := step_output _gen9"; this.nonterminal_rules.get("_gen8").add(rule); + this.rules.put(new Integer(38), rule); + rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(39), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; - this.nonterminal_rules.get("for_loop").add(rule); - this.rules.put(new Integer(40), rule); - rule = "wdl_entity := composite_task"; - this.nonterminal_rules.get("wdl_entity").add(rule); - this.rules.put(new Integer(41), rule); rule = "_gen0 := wdl_entity _gen0"; this.nonterminal_rules.get("_gen0").add(rule); + this.rules.put(new Integer(40), rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + this.nonterminal_rules.get("task_attr").add(rule); + this.rules.put(new Integer(41), rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(42), rule); - rule = "step_attr := step_output_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(43), rule); - rule = "_gen3 := step_attr _gen3"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "task_identifier := 'identifier' _gen4 -> Task( attributes=$1, name=$0 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(44), rule); - this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); - this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); - this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen0", new TerminalId[] { }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); this.follow.put("wdl", new TerminalId[] { }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); } public TerminalMap getTerminalMap() { return new WdlTerminalMap(TerminalId.values()); @@ -351,63 +352,12 @@ private boolean isTerminal(int terminal) { private boolean isNonTerminal(int terminal) { return (22 <= terminal && terminal <= 50); } - private ParseTree parse_wdl_entity() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "wdl_entity")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "wdl_entity", - Arrays.asList(this.first.get("wdl_entity")), - this.nonterminal_rules.get("wdl_entity") - )); - } - if (rule == 41) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); - tree.add( subtree); - return tree; - } - List terminals = Arrays.asList(this.first.get("wdl_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl_entity", - current, - Arrays.asList(this.first.get("wdl_entity")), - this.rules.get(41) - )); - } - private ParseTree parse__gen10() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen10")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 12 || current.getId() == 20) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 14) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); - tree.add( subtree); - return tree; - } - return tree; - } private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "step")); + int rule = current != null ? this.table[0][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(22, "step")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -416,23 +366,23 @@ private ParseTree parse_step() throws SyntaxError { this.nonterminal_rules.get("step") )); } - if (rule == 24) { + if (rule == 1) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 4); parameters.put("task", 1); parameters.put("name", 2); tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(24)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(1)); tree.add(next); subtree = this.parse_task_identifier(); tree.add( subtree); subtree = this.parse__gen2(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(24)); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(1)); tree.add(next); subtree = this.parse__gen3(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(24)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(1)); tree.add(next); return tree; } @@ -441,123 +391,151 @@ private ParseTree parse_step() throws SyntaxError { "step", current, Arrays.asList(this.first.get("step")), - this.rules.get(24) + this.rules.get(1) )); } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "task_attr")); + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "composite_task")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") )); } - if (rule == 10) { + if (rule == 4) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(10)); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(4)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(10)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(4)); tree.add(next); - subtree = this.parse_task_attr_value(); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(4)); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(4)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr")); + List terminals = Arrays.asList(this.first.get("composite_task")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", + "composite_task", current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(10) + Arrays.asList(this.first.get("composite_task")), + this.rules.get(4) )); } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "step_input_list")); - tree.setList(null); + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen5")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") - )); + return tree; } - if (rule == 29) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(29)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(29)); - tree.add(next); - subtree = this.parse__gen6(); + if (rule == 6) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen5(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(29)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", - current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(29) - )); + return tree; } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "_gen5")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "_gen0")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 14) { + if (current.getId() == -1) { return tree; } } if (current == null) { return tree; } - if (rule == 37) { + if (rule == 40) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); + subtree = this.parse_wdl_entity(); tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } + private ParseTree parse_task_attr() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "task_attr")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") + )); + } + if (rule == 41) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(41)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(41)); + tree.add(next); + subtree = this.parse_task_attr_value(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("task_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr", + current, + Arrays.asList(this.first.get("task_attr")), + this.rules.get(41) + )); + } private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "_gen9")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "_gen9")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 12) { + if (current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 33) { + if (rule == 8) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(33)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(8)); tree.add(next); tree.setListSeparator(next); subtree = this.parse_step_output(); @@ -568,136 +546,145 @@ private ParseTree parse__gen9() throws SyntaxError { } return tree; } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "variable_member")); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "step_output_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") )); } - if (rule == 22) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(22)); + if (rule == 39) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(39)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(22)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(39)); + tree.add(next); + subtree = this.parse__gen8(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(39)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_output_list")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_output_list", + current, + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(39) + )); + } + private ParseTree parse__gen7() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "_gen7")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 8) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 2) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(2)); tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen7(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable_member")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", - current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(22) - )); + return tree; } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "_gen2")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(30, "_gen6")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 21) { + if (current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 21) { + if (rule == 32) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "for_loop")); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen2")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 11) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "for_loop", - Arrays.asList(this.first.get("for_loop")), - this.nonterminal_rules.get("for_loop") - )); + return tree; } - if (rule == 40) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(40)); - tree.add(next); - subtree = this.parse__gen1(); + if (rule == 12) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_name(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(40)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("for_loop")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "for_loop", - current, - Arrays.asList(this.first.get("for_loop")), - this.rules.get(40) - )); + return tree; } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "task_attrs")); + ParseTree tree = new ParseTree( new NonTerminal(32, "step_name")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attrs", - Arrays.asList(this.first.get("task_attrs")), - this.nonterminal_rules.get("task_attrs") + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") )); } if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(27)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(27)); tree.add(next); - subtree = this.parse__gen5(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(27)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(27)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attrs")); + List terminals = Arrays.asList(this.first.get("step_name")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attrs", + "step_name", current, - Arrays.asList(this.first.get("task_attrs")), + Arrays.asList(this.first.get("step_name")), this.rules.get(27) )); } @@ -715,21 +702,21 @@ private ParseTree parse_composite_task_entity() throws SyntaxError { this.nonterminal_rules.get("composite_task_entity") )); } - if (rule == 4) { + if (rule == 3) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + subtree = this.parse_step(); tree.add( subtree); return tree; } - else if (rule == 6) { + else if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - else if (rule == 30) { + else if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_for_loop(); tree.add( subtree); return tree; } @@ -738,167 +725,269 @@ else if (rule == 30) { "composite_task_entity", current, Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(30) + this.rules.get(20) )); } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "step_name")); + ParseTree tree = new ParseTree( new NonTerminal(34, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_name", - Arrays.asList(this.first.get("step_name")), - this.nonterminal_rules.get("step_name") + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") )); } - if (rule == 34) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(34)); + if (rule == 26) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(26)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(26)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(26)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(26)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(34)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(26)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(26)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(26)); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(26)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_name")); + List terminals = Arrays.asList(this.first.get("for_loop")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_name", + "for_loop", current, - Arrays.asList(this.first.get("step_name")), - this.rules.get(34) + Arrays.asList(this.first.get("for_loop")), + this.rules.get(26) )); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "_gen3")); + ParseTree tree = new ParseTree( new NonTerminal(35, "_gen1")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 10) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 44) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "_gen4")); + ParseTree tree = new ParseTree( new NonTerminal(36, "variable")); tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") + )); + } + if (rule == 9) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(9)); + tree.add(next); + subtree = this.parse__gen10(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("variable")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable", + current, + Arrays.asList(this.first.get("variable")), + this.rules.get(9) + )); + } + private ParseTree parse__gen8() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "_gen8")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 4) { + if (current.getId() == 8) { return tree; } } if (current == null) { return tree; } - if (rule == 19) { + if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step_output")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "task_identifier")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "task_identifier", + Arrays.asList(this.first.get("task_identifier")), + this.nonterminal_rules.get("task_identifier") )); } - if (rule == 12) { + if (rule == 44) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(12)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(12)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(12)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(12)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(12)); + parameters.put("attributes", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(44)); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + List terminals = Arrays.asList(this.first.get("task_identifier")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "task_identifier", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(12) + Arrays.asList(this.first.get("task_identifier")), + this.rules.get(44) )); } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "task_identifier")); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "step_input")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_identifier", - Arrays.asList(this.first.get("task_identifier")), - this.nonterminal_rules.get("task_identifier") + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") )); } - if (rule == 26) { + if (rule == 29) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(26)); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(29)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(29)); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_input")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_input", + current, + Arrays.asList(this.first.get("step_input")), + this.rules.get(29) + )); + } + private ParseTree parse__gen10() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen10")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 12 || current.getId() == 8) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 33) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_variable_member(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_task_attrs() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "task_attrs")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") + )); + } + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(10)); tree.add(next); - subtree = this.parse__gen4(); + subtree = this.parse__gen5(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(10)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_identifier")); + List terminals = Arrays.asList(this.first.get("task_attrs")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_identifier", + "task_attrs", current, - Arrays.asList(this.first.get("task_identifier")), - this.rules.get(26) + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(10) )); } private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "step_attr")); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "step_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -907,13 +996,13 @@ private ParseTree parse_step_attr() throws SyntaxError { this.nonterminal_rules.get("step_attr") )); } - if (rule == 9) { + if (rule == 5) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_input_list(); tree.add( subtree); return tree; } - else if (rule == 43) { + else if (rule == 18) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_output_list(); tree.add( subtree); @@ -924,161 +1013,98 @@ else if (rule == 43) { "step_attr", current, Arrays.asList(this.first.get("step_attr")), - this.rules.get(43) + this.rules.get(18) )); } - private ParseTree parse__gen6() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen6")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 12) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 38) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "step_input")); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "variable_member")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") )); } - if (rule == 2) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(2)); + if (rule == 24) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(24)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(2)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(24)); tree.add(next); - subtree = this.parse_variable(); - tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); + List terminals = Arrays.asList(this.first.get("variable_member")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", + "variable_member", current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(2) + Arrays.asList(this.first.get("variable_member")), + this.rules.get(24) )); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "_gen1")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 10) { - return tree; - } - } + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "wdl_entity")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "wdl_entity", + Arrays.asList(this.first.get("wdl_entity")), + this.nonterminal_rules.get("wdl_entity") + )); } - if (rule == 18) { + if (rule == 17) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); - tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("wdl_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "wdl_entity", + current, + Arrays.asList(this.first.get("wdl_entity")), + this.rules.get(17) + )); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen0")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "_gen3")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 42) { + if (rule == 22) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_output_list() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "step_output_list")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") - )); - } - if (rule == 15) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(15)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(15)); - tree.add(next); - subtree = this.parse__gen8(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(15)); - tree.add(next); - return tree; - } - List terminals = Arrays.asList(this.first.get("step_output_list")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", - current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(15) - )); - } private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "task_attr_value")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -1087,21 +1113,21 @@ private ParseTree parse_task_attr_value() throws SyntaxError { this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 3) { + if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(3)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(11)); tree.add(next); return tree; } - else if (rule == 17) { + else if (rule == 31) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(31)); tree.add(next); return tree; } - else if (rule == 31) { + else if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(31)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(37)); tree.add(next); return tree; } @@ -1110,153 +1136,128 @@ else if (rule == 31) { "task_attr_value", current, Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(31) + this.rules.get(37) )); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "variable")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "wdl")); tree.setList(null); if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable", - Arrays.asList(this.first.get("variable")), - this.nonterminal_rules.get("variable") - )); + return tree; } - if (rule == 20) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(20)); - tree.add(next); - subtree = this.parse__gen10(); + if (rule == 15) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable")); + List terminals = Arrays.asList(this.first.get("wdl")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable", + "wdl", current, - Arrays.asList(this.first.get("variable")), - this.rules.get(20) + Arrays.asList(this.first.get("wdl")), + this.rules.get(15) )); } - private ParseTree parse__gen8() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "_gen8")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 12) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 25) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen9(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "wdl")); + ParseTree tree = new ParseTree( new NonTerminal(48, "step_output")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") + )); } - if (rule == 0) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); + if (rule == 23) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(23)); + tree.add(next); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("wdl")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl", + "step_output", current, - Arrays.asList(this.first.get("wdl")), - this.rules.get(0) + Arrays.asList(this.first.get("step_output")), + this.rules.get(23) )); } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "composite_task")); + ParseTree tree = new ParseTree( new NonTerminal(49, "step_input_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task", - Arrays.asList(this.first.get("composite_task")), - this.nonterminal_rules.get("composite_task") + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") )); } - if (rule == 28) { + if (rule == 21) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(28)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(28)); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(21)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(28)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(21)); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse__gen6(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(28)); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(21)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task")); + List terminals = Arrays.asList(this.first.get("step_input_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task", + "step_input_list", current, - Arrays.asList(this.first.get("composite_task")), - this.rules.get(28) + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(21) )); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen7")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen4")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 12) { + if (current.getId() == 13) { return tree; } } if (current == null) { return tree; } - if (rule == 1) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(1)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } diff --git a/src/WdlSourceCode.java b/src/org/broadinstitute/compositetask/WdlSourceCode.java similarity index 96% rename from src/WdlSourceCode.java rename to src/org/broadinstitute/compositetask/WdlSourceCode.java index a50d875..9c526d1 100644 --- a/src/WdlSourceCode.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCode.java @@ -1,3 +1,5 @@ +package org.broadinstitute.compositetask; + import java.io.File; import java.io.IOException; import java.io.FileNotFoundException; @@ -10,7 +12,7 @@ import java.util.List; import java.io.FileInputStream; -class WdlSourceCode implements SourceCode{ +public class WdlSourceCode implements SourceCode{ private File source; private String resource; private String contents; diff --git a/src/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java similarity index 86% rename from src/WdlSourceCodeFormatter.java rename to src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java index 92322da..b724919 100644 --- a/src/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java @@ -1,4 +1,6 @@ -class WdlSourceCodeFormatter { +package org.broadinstitute.compositetask; + +public class WdlSourceCodeFormatter { private WdlTerminalColorizer colorizer; private WdlSourceCodeNormalizer normalizer; diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java b/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java new file mode 100644 index 0000000..13eeab3 --- /dev/null +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java @@ -0,0 +1,7 @@ +package org.broadinstitute.compositetask; + +public class WdlSourceCodeNormalizer { + ParseTree format(ParseTree tree) { + return null; + } +} diff --git a/src/WdlSyntaxErrorFormatter.java b/src/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java similarity index 97% rename from src/WdlSyntaxErrorFormatter.java rename to src/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java index 59404c5..ef89e0f 100644 --- a/src/WdlSyntaxErrorFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java @@ -1,7 +1,9 @@ +package org.broadinstitute.compositetask; + import java.util.ArrayList; import java.util.List; -class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { +public class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { private SourceCode code; public void setSourceCode(SourceCode code) { this.code = code; diff --git a/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java b/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java new file mode 100644 index 0000000..91c5b68 --- /dev/null +++ b/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java @@ -0,0 +1,5 @@ +package org.broadinstitute.compositetask; + +public interface WdlTerminalColorizer { + String colorize(Terminal terminal); +} From 9925bca53e0d92e062ca099f36c0980cec0738fc Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 31 Aug 2012 12:53:31 -0400 Subject: [PATCH 072/140] forgot public everywhere --- src/org/broadinstitute/compositetask/Ast.java | 2 +- src/org/broadinstitute/compositetask/AstList.java | 2 +- src/org/broadinstitute/compositetask/AstNode.java | 2 +- src/org/broadinstitute/compositetask/AstTransform.java | 2 +- src/org/broadinstitute/compositetask/AstTransformNodeCreator.java | 2 +- src/org/broadinstitute/compositetask/AstTransformSubstitution.java | 2 +- src/org/broadinstitute/compositetask/ExpressionParser.java | 2 +- src/org/broadinstitute/compositetask/NonTerminal.java | 2 +- src/org/broadinstitute/compositetask/ParseTree.java | 2 +- src/org/broadinstitute/compositetask/Parser.java | 2 +- src/org/broadinstitute/compositetask/SourceCode.java | 2 +- src/org/broadinstitute/compositetask/SyntaxError.java | 2 +- src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java | 2 +- src/org/broadinstitute/compositetask/Terminal.java | 2 +- src/org/broadinstitute/compositetask/TerminalIdentifier.java | 2 +- src/org/broadinstitute/compositetask/TerminalMap.java | 2 +- src/org/broadinstitute/compositetask/TokenStream.java | 2 +- src/org/broadinstitute/compositetask/Utility.java | 2 +- src/org/broadinstitute/compositetask/WdlParser.java | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/org/broadinstitute/compositetask/Ast.java b/src/org/broadinstitute/compositetask/Ast.java index 451f022..c26df6c 100644 --- a/src/org/broadinstitute/compositetask/Ast.java +++ b/src/org/broadinstitute/compositetask/Ast.java @@ -5,7 +5,7 @@ import java.util.Formatter; import java.util.Locale; import java.util.ArrayList; -class Ast implements AstNode { +public class Ast implements AstNode { private String name; private Map attributes; Ast(String name, Map attributes) { diff --git a/src/org/broadinstitute/compositetask/AstList.java b/src/org/broadinstitute/compositetask/AstList.java index 5ebfc6f..7405e1e 100644 --- a/src/org/broadinstitute/compositetask/AstList.java +++ b/src/org/broadinstitute/compositetask/AstList.java @@ -1,7 +1,7 @@ package org.broadinstitute.compositetask; import java.util.ArrayList; -class AstList extends ArrayList implements AstNode { +public class AstList extends ArrayList implements AstNode { public String toString() { return "[" + Utility.join(this, ", ") + "]"; } diff --git a/src/org/broadinstitute/compositetask/AstNode.java b/src/org/broadinstitute/compositetask/AstNode.java index ce7930b..1e5c788 100644 --- a/src/org/broadinstitute/compositetask/AstNode.java +++ b/src/org/broadinstitute/compositetask/AstNode.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -interface AstNode { +public interface AstNode { public String toString(); public String toPrettyString(); public String toPrettyString(int indent); diff --git a/src/org/broadinstitute/compositetask/AstTransform.java b/src/org/broadinstitute/compositetask/AstTransform.java index e75e489..0ae30b6 100644 --- a/src/org/broadinstitute/compositetask/AstTransform.java +++ b/src/org/broadinstitute/compositetask/AstTransform.java @@ -1,3 +1,3 @@ package org.broadinstitute.compositetask; -interface AstTransform {} +public interface AstTransform {} diff --git a/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java b/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java index 19c357b..39292a8 100644 --- a/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java +++ b/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java @@ -3,7 +3,7 @@ import java.util.LinkedList; import java.util.Map; import java.util.LinkedHashMap; -class AstTransformNodeCreator implements AstTransform { +public class AstTransformNodeCreator implements AstTransform { private String name; private LinkedHashMap parameters; AstTransformNodeCreator(String name, LinkedHashMap parameters) { diff --git a/src/org/broadinstitute/compositetask/AstTransformSubstitution.java b/src/org/broadinstitute/compositetask/AstTransformSubstitution.java index 32a8a2d..d5d9c3e 100644 --- a/src/org/broadinstitute/compositetask/AstTransformSubstitution.java +++ b/src/org/broadinstitute/compositetask/AstTransformSubstitution.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -class AstTransformSubstitution implements AstTransform { +public class AstTransformSubstitution implements AstTransform { private int index; AstTransformSubstitution(int index) { this.index = index; diff --git a/src/org/broadinstitute/compositetask/ExpressionParser.java b/src/org/broadinstitute/compositetask/ExpressionParser.java index a4f2b6d..b478cb7 100644 --- a/src/org/broadinstitute/compositetask/ExpressionParser.java +++ b/src/org/broadinstitute/compositetask/ExpressionParser.java @@ -1,5 +1,5 @@ package org.broadinstitute.compositetask; -interface ExpressionParser extends Parser { +public interface ExpressionParser extends Parser { ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; } diff --git a/src/org/broadinstitute/compositetask/NonTerminal.java b/src/org/broadinstitute/compositetask/NonTerminal.java index 08a45ef..70bd55d 100644 --- a/src/org/broadinstitute/compositetask/NonTerminal.java +++ b/src/org/broadinstitute/compositetask/NonTerminal.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -class NonTerminal { +public class NonTerminal { private int id; private String string; NonTerminal(int id, String string) { diff --git a/src/org/broadinstitute/compositetask/ParseTree.java b/src/org/broadinstitute/compositetask/ParseTree.java index 8270387..f9c0626 100644 --- a/src/org/broadinstitute/compositetask/ParseTree.java +++ b/src/org/broadinstitute/compositetask/ParseTree.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.List; import java.util.LinkedHashMap; -class ParseTree implements ParseTreeNode { +public class ParseTree implements ParseTreeNode { private NonTerminal nonterminal; private ArrayList children; private boolean isExpr, isNud, isPrefix, isInfix, isExprNud; diff --git a/src/org/broadinstitute/compositetask/Parser.java b/src/org/broadinstitute/compositetask/Parser.java index d9fcf1f..9467fef 100644 --- a/src/org/broadinstitute/compositetask/Parser.java +++ b/src/org/broadinstitute/compositetask/Parser.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -interface Parser { +public interface Parser { ParseTree parse(TokenStream tokens) throws SyntaxError; TerminalMap getTerminalMap(); } diff --git a/src/org/broadinstitute/compositetask/SourceCode.java b/src/org/broadinstitute/compositetask/SourceCode.java index 6335edc..4d4293d 100644 --- a/src/org/broadinstitute/compositetask/SourceCode.java +++ b/src/org/broadinstitute/compositetask/SourceCode.java @@ -1,7 +1,7 @@ package org.broadinstitute.compositetask; import java.util.List; -interface SourceCode { +public interface SourceCode { public void advance(int amount); public List getLines(); public String getLine(int lineno); diff --git a/src/org/broadinstitute/compositetask/SyntaxError.java b/src/org/broadinstitute/compositetask/SyntaxError.java index 90e0098..b42f680 100644 --- a/src/org/broadinstitute/compositetask/SyntaxError.java +++ b/src/org/broadinstitute/compositetask/SyntaxError.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -class SyntaxError extends Exception { +public class SyntaxError extends Exception { SyntaxError(String message) { super(message); } diff --git a/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java b/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java index 5822b13..4c7e425 100644 --- a/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java +++ b/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java @@ -1,7 +1,7 @@ package org.broadinstitute.compositetask; import java.util.List; -interface SyntaxErrorFormatter { +public interface SyntaxErrorFormatter { /* Called when the parser runs out of tokens but isn't finished parsing. */ String unexpected_eof(String method, List expected, List nt_rules); /* Called when the parser finished parsing but there are still tokens left in the stream. */ diff --git a/src/org/broadinstitute/compositetask/Terminal.java b/src/org/broadinstitute/compositetask/Terminal.java index 1fa5987..894b330 100644 --- a/src/org/broadinstitute/compositetask/Terminal.java +++ b/src/org/broadinstitute/compositetask/Terminal.java @@ -2,7 +2,7 @@ package org.broadinstitute.compositetask; import java.util.Formatter; import java.util.Locale; -class Terminal implements AstNode, ParseTreeNode +public class Terminal implements AstNode, ParseTreeNode { private int id; private String terminal_str; diff --git a/src/org/broadinstitute/compositetask/TerminalIdentifier.java b/src/org/broadinstitute/compositetask/TerminalIdentifier.java index 4039353..1a2f4e0 100644 --- a/src/org/broadinstitute/compositetask/TerminalIdentifier.java +++ b/src/org/broadinstitute/compositetask/TerminalIdentifier.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -interface TerminalIdentifier { +public interface TerminalIdentifier { public int id(); public String string(); } diff --git a/src/org/broadinstitute/compositetask/TerminalMap.java b/src/org/broadinstitute/compositetask/TerminalMap.java index 1ea4329..da03eda 100644 --- a/src/org/broadinstitute/compositetask/TerminalMap.java +++ b/src/org/broadinstitute/compositetask/TerminalMap.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -interface TerminalMap { +public interface TerminalMap { int get(String string); String get(int id); boolean isValid(String string); diff --git a/src/org/broadinstitute/compositetask/TokenStream.java b/src/org/broadinstitute/compositetask/TokenStream.java index adae466..9fb0616 100644 --- a/src/org/broadinstitute/compositetask/TokenStream.java +++ b/src/org/broadinstitute/compositetask/TokenStream.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Formatter; import java.util.Locale; -class TokenStream extends ArrayList { +public class TokenStream extends ArrayList { private int index; private TerminalMap terminals; private SyntaxErrorFormatter syntaxErrorFormatter; diff --git a/src/org/broadinstitute/compositetask/Utility.java b/src/org/broadinstitute/compositetask/Utility.java index 04b8871..f8a6e1d 100644 --- a/src/org/broadinstitute/compositetask/Utility.java +++ b/src/org/broadinstitute/compositetask/Utility.java @@ -10,7 +10,7 @@ import java.nio.*; import java.nio.channels.FileChannel; import java.nio.charset.Charset; -class Utility { +public class Utility { public static String join(Collection s, String delimiter) { StringBuilder builder = new StringBuilder(); Iterator iter = s.iterator(); diff --git a/src/org/broadinstitute/compositetask/WdlParser.java b/src/org/broadinstitute/compositetask/WdlParser.java index 7a33b0d..c351a1a 100644 --- a/src/org/broadinstitute/compositetask/WdlParser.java +++ b/src/org/broadinstitute/compositetask/WdlParser.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Arrays; -class WdlParser implements Parser { +public class WdlParser implements Parser { private TokenStream tokens; private HashMap expressionParsers; private SyntaxErrorFormatter syntaxErrorFormatter; From 51396540efacf3001b3a178102ac6f51a8d27a6d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 31 Aug 2012 13:01:56 -0400 Subject: [PATCH 073/140] public constructors --- src/org/broadinstitute/compositetask/CompositeTask.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index d6ee03d..e54a6e0 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -247,7 +247,7 @@ private CompositeTask(String name, Set nodes) { this.parent = null; } - CompositeTask(SourceCode source_code) throws SyntaxError { + public CompositeTask(SourceCode source_code) throws SyntaxError { this.error_formatter = new WdlSyntaxErrorFormatter(); this.error_formatter.setSourceCode(source_code); ParseTreeNode node = getParseTree(source_code); @@ -258,11 +258,11 @@ private CompositeTask(String name, Set nodes) { this.parent = null; } - CompositeTask(File source_code) throws SyntaxError, IOException { + public CompositeTask(File source_code) throws SyntaxError, IOException { this(new WdlSourceCode(source_code)); } - CompositeTask(String source_code, String resource) throws SyntaxError { + public CompositeTask(String source_code, String resource) throws SyntaxError { this(new WdlSourceCode(source_code, resource)); } From 539c3af80dc7e19f21fb9cdb0e23610247a6838e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 10 Sep 2012 13:11:11 -0400 Subject: [PATCH 074/140] implementing some unfinished methods --- .../compositetask/CompositeTask.java | 34 ++++++++++++++++++++-- .../compositetask/CompositeTaskSubTask.java | 7 +++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index e54a6e0..b0a4fbe 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -55,6 +55,7 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { AstList ctNodes = (AstList) composite_task.getAttribute("body"); CompositeTask.this.nodes = new HashSet(); + CompositeTask.this.name = ((Terminal) composite_task.getAttribute("name")).getSourceString(); for ( AstNode ctNode : ctNodes ) { Ast node = (Ast) ctNode; @@ -285,15 +286,42 @@ public CompositeTaskGraph getGraph() { } public CompositeTaskStep getStep(String name) { + return getStep(this, name); + } + + private static CompositeTaskStep getStep(CompositeTaskScope scope, String name) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + if ( step.getName().equals(name) ) { + return step; + } + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskStep step = getStep((CompositeTaskScope) node, name); + if ( step != null ) { + return step; + } + } + } return null; } public Set getTasks() { - return null; + return getTasks(this); } - private Set getTasks(CompositeTaskScope scope) { - return null; + private static Set getTasks(CompositeTaskScope scope) { + Set tasks = new HashSet(); + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + tasks.add(step.getTask()); + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskScope subScope = (CompositeTaskScope) node; + tasks.addAll( getTasks(subScope) ); + } + } + return tasks; } public Ast getAst() { diff --git a/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java b/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java index 76a1be5..7d59315 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java @@ -24,6 +24,13 @@ public String getVersion() { return null; } + public boolean equals(CompositeTaskSubTask other) { + if (other.getTaskName().equals(this.name) && other.getVersion().equals(this.version)) { + return true; + } + return false; + } + public String toString() { return "[Task: name="+this.name+", version="+this.version+"]"; } From e1e7cf5b0efb67b7ed3e3007811875dd1c7dfaf5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Sep 2012 10:02:55 -0400 Subject: [PATCH 075/140] First draft of syntax reformatting and highlighting --- examples/unformatted.wdl | 8 +++ .../compositetask/AnsiColorizer.java | 27 ++++++++ .../{WdlColorTheme.java => ColorTheme.java} | 2 +- .../compositetask/CompositeTask.java | 62 ++++++++--------- .../compositetask/CompositeTaskColorizer.java | 9 +++ .../compositetask/HtmlColorizer.java | 29 ++++++++ .../compositetask/NullColorizer.java | 23 +++++++ .../compositetask/WdlAnsiColorizer.java | 11 ---- .../compositetask/WdlHtmlColorizer.java | 11 ---- src/org/broadinstitute/compositetask/WdlMain.java | 6 +- .../compositetask/WdlSourceCodeFormatter.java | 77 +++++++++++++++++++--- .../compositetask/WdlTerminalColorizer.java | 5 -- 12 files changed, 200 insertions(+), 70 deletions(-) create mode 100644 examples/unformatted.wdl create mode 100644 src/org/broadinstitute/compositetask/AnsiColorizer.java rename src/org/broadinstitute/compositetask/{WdlColorTheme.java => ColorTheme.java} (76%) create mode 100644 src/org/broadinstitute/compositetask/CompositeTaskColorizer.java create mode 100644 src/org/broadinstitute/compositetask/HtmlColorizer.java create mode 100644 src/org/broadinstitute/compositetask/NullColorizer.java delete mode 100644 src/org/broadinstitute/compositetask/WdlAnsiColorizer.java delete mode 100644 src/org/broadinstitute/compositetask/WdlHtmlColorizer.java delete mode 100644 src/org/broadinstitute/compositetask/WdlTerminalColorizer.java diff --git a/examples/unformatted.wdl b/examples/unformatted.wdl new file mode 100644 index 0000000..0989568 --- /dev/null +++ b/examples/unformatted.wdl @@ -0,0 +1,8 @@ +composite_task foo { + step atask[version=0] {output: File("foo.txt") as x;} + for ( item in foo ) { + step btask[version=0] {input: p0=x, p1=item, p2=GLOBAL; output: File("bar.txt") as y;} + step ctask[version=0] {input: p0=x, p1=item, p2=y; output: File("quux.txt") as z;} + } + step dtask[version=0] {input: p0=x, p1=y, p2=z; output: File("report.txt") as r;} +} diff --git a/src/org/broadinstitute/compositetask/AnsiColorizer.java b/src/org/broadinstitute/compositetask/AnsiColorizer.java new file mode 100644 index 0000000..3448399 --- /dev/null +++ b/src/org/broadinstitute/compositetask/AnsiColorizer.java @@ -0,0 +1,27 @@ +package org.broadinstitute.compositetask; + +public class AnsiColorizer implements CompositeTaskColorizer { + public AnsiColorizer() { + + } + + public String preamble() { + return ""; + } + + public String postamble() { + return ""; + } + + public String keyword(String str) { + return "\033[38;5;109m" + str + "\033[0m"; + } + + public String string(String str) { + return "\033[38;5;222m" + str + "\033[0m"; + } + + public String variable(String str) { + return "\033[38;5;143m" + str + "\033[0m"; + } +} diff --git a/src/org/broadinstitute/compositetask/WdlColorTheme.java b/src/org/broadinstitute/compositetask/ColorTheme.java similarity index 76% rename from src/org/broadinstitute/compositetask/WdlColorTheme.java rename to src/org/broadinstitute/compositetask/ColorTheme.java index 7651276..d7864b9 100644 --- a/src/org/broadinstitute/compositetask/WdlColorTheme.java +++ b/src/org/broadinstitute/compositetask/ColorTheme.java @@ -2,6 +2,6 @@ import java.awt.Color; -public interface WdlColorTheme { +public interface ColorTheme { Color getColor(Terminal terminal); } diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index b0a4fbe..8b0f4b3 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -289,41 +289,10 @@ public CompositeTaskStep getStep(String name) { return getStep(this, name); } - private static CompositeTaskStep getStep(CompositeTaskScope scope, String name) { - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - if ( step.getName().equals(name) ) { - return step; - } - } else if ( node instanceof CompositeTaskScope ) { - CompositeTaskStep step = getStep((CompositeTaskScope) node, name); - if ( step != null ) { - return step; - } - } - } - return null; - } - public Set getTasks() { return getTasks(this); } - private static Set getTasks(CompositeTaskScope scope) { - Set tasks = new HashSet(); - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - tasks.add(step.getTask()); - } else if ( node instanceof CompositeTaskScope ) { - CompositeTaskScope subScope = (CompositeTaskScope) node; - tasks.addAll( getTasks(subScope) ); - } - } - return tasks; - } - public Ast getAst() { return this.ast; } @@ -372,4 +341,35 @@ private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { TokenStream tokens = new TokenStream(terminals); return parser.parse(tokens); } + + private static Set getTasks(CompositeTaskScope scope) { + Set tasks = new HashSet(); + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + tasks.add(step.getTask()); + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskScope subScope = (CompositeTaskScope) node; + tasks.addAll( getTasks(subScope) ); + } + } + return tasks; + } + + private static CompositeTaskStep getStep(CompositeTaskScope scope, String name) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + if ( step.getName().equals(name) ) { + return step; + } + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskStep step = getStep((CompositeTaskScope) node, name); + if ( step != null ) { + return step; + } + } + } + return null; + } } diff --git a/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java b/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java new file mode 100644 index 0000000..844fdb5 --- /dev/null +++ b/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java @@ -0,0 +1,9 @@ +package org.broadinstitute.compositetask; + +public interface CompositeTaskColorizer { + String preamble(); + String postamble(); + String keyword(String str); + String string(String str); + String variable(String str); +} diff --git a/src/org/broadinstitute/compositetask/HtmlColorizer.java b/src/org/broadinstitute/compositetask/HtmlColorizer.java new file mode 100644 index 0000000..3d17a0f --- /dev/null +++ b/src/org/broadinstitute/compositetask/HtmlColorizer.java @@ -0,0 +1,29 @@ +package org.broadinstitute.compositetask; + +public class HtmlColorizer implements CompositeTaskColorizer { + private ColorTheme theme; + + public HtmlColorizer(ColorTheme theme) { + this.theme = theme; + } + + public String preamble() { + return ""; + } + + public String postamble() { + return ""; + } + + public String keyword(String str) { + return str; + } + + public String string(String str) { + return str; + } + + public String variable(String str) { + return str; + } +} diff --git a/src/org/broadinstitute/compositetask/NullColorizer.java b/src/org/broadinstitute/compositetask/NullColorizer.java new file mode 100644 index 0000000..df146c7 --- /dev/null +++ b/src/org/broadinstitute/compositetask/NullColorizer.java @@ -0,0 +1,23 @@ +package org.broadinstitute.compositetask; + +public class NullColorizer implements CompositeTaskColorizer { + public String preamble() { + return ""; + } + + public String postamble() { + return ""; + } + + public String keyword(String str) { + return str; + } + + public String string(String str) { + return str; + } + + public String variable(String str) { + return str; + } +} diff --git a/src/org/broadinstitute/compositetask/WdlAnsiColorizer.java b/src/org/broadinstitute/compositetask/WdlAnsiColorizer.java deleted file mode 100644 index 6fcfbb5..0000000 --- a/src/org/broadinstitute/compositetask/WdlAnsiColorizer.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.broadinstitute.compositetask; - -public class WdlAnsiColorizer implements WdlTerminalColorizer { - WdlAnsiColorizer(WdlColorTheme theme) { - - } - - public String colorize(Terminal terminal) { - return null; - } -} diff --git a/src/org/broadinstitute/compositetask/WdlHtmlColorizer.java b/src/org/broadinstitute/compositetask/WdlHtmlColorizer.java deleted file mode 100644 index 4c1f874..0000000 --- a/src/org/broadinstitute/compositetask/WdlHtmlColorizer.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.broadinstitute.compositetask; - -public class WdlHtmlColorizer implements WdlTerminalColorizer { - WdlHtmlColorizer(WdlColorTheme theme) { - - } - - public String colorize(Terminal terminal) { - return null; - } -} diff --git a/src/org/broadinstitute/compositetask/WdlMain.java b/src/org/broadinstitute/compositetask/WdlMain.java index c8d7190..c65cc2b 100644 --- a/src/org/broadinstitute/compositetask/WdlMain.java +++ b/src/org/broadinstitute/compositetask/WdlMain.java @@ -9,7 +9,7 @@ public class WdlMain { public static void usage() { - System.err.println("Usage: <.wdl file> "); + System.err.println("Usage: <.wdl file> "); System.exit(-1); } @@ -46,6 +46,10 @@ public static void main(String[] args) { System.out.println(v); } + } else if ( args[1].equals("format") ) { + WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(new AnsiColorizer()); + String formatted = formatter.format(ctask); + System.out.println(formatted); } else { usage(); } diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java index b724919..380dccb 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java @@ -1,23 +1,80 @@ package org.broadinstitute.compositetask; +import java.util.ArrayList; +import java.util.List; + public class WdlSourceCodeFormatter { - private WdlTerminalColorizer colorizer; - private WdlSourceCodeNormalizer normalizer; + private CompositeTaskColorizer colorizer; - WdlSourceCodeFormatter(WdlTerminalColorizer colorizer, WdlSourceCodeNormalizer normalizer) { + WdlSourceCodeFormatter(CompositeTaskColorizer colorizer) { this.colorizer = colorizer; - this.normalizer = normalizer; } - WdlSourceCodeFormatter(WdlTerminalColorizer colorizer) { - this.colorizer = colorizer; + WdlSourceCodeFormatter() { + this(new NullColorizer()); } - WdlSourceCodeFormatter(WdlSourceCodeNormalizer normalizer) { - this.normalizer = normalizer; + public String format(CompositeTask ctask) { + return format(ctask, 0); } - public String compile(CompositeTask task) { - return null; + private String format(CompositeTaskNode node, int indent) { + StringBuilder builder = new StringBuilder(); + String indent_str = Utility.getIndentString(indent); + if ( node instanceof CompositeTask ) { + CompositeTask ctask = (CompositeTask) node; + builder.append(indent_str + this.colorizer.keyword("composite_task") + " " + ctask.getName() + " {\n"); + for ( CompositeTaskNode sub_node : ctask.getNodes() ) { + builder.append( indent_str ); + builder.append( format(sub_node, indent + 2) ); + } + builder.append(indent_str + "}\n"); + } else if ( node instanceof CompositeTaskForLoop ) { + CompositeTaskForLoop loop = (CompositeTaskForLoop) node; + builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " : " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); + for ( CompositeTaskNode sub_node : loop.getNodes() ) { + builder.append( indent_str ); + builder.append( format(sub_node, indent + 2) ); + } + builder.append( indent_str + "}\n" ); + } else if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + CompositeTaskSubTask task = step.getTask(); + String rename = ""; + if ( !step.getName().equals(task.getTaskName()) ) { + rename = " " + this.colorizer.keyword("as") + " " + step.getName(); + } + builder.append( " " + this.colorizer.keyword("step") + " " + task.getTaskName() + "[version=" + task.getVersion() + "]" + rename + " {\n" ); + + if ( step.getInputs().size() > 0 ) { + List parameters = new ArrayList(); + for ( CompositeTaskStepInput input : step.getInputs() ) { + parameters.add(input.getParameter() + "=" + this.colorizer.variable(variable_to_string(input.getVariable()))); + } + + builder.append(indent_str + " " + this.colorizer.keyword("input") + ": " + Utility.join(parameters, ", ") + ";\n"); + } + + if ( step.getOutputs().size() > 0 ) { + List outputs = new ArrayList(); + for ( CompositeTaskStepOutput output : step.getOutputs() ) { + outputs.add(output.getType() + "(" + this.colorizer.string(output.getPath()) + ") " + this.colorizer.keyword("as") + " " + this.colorizer.variable(variable_to_string(output.getVariable()))); + } + + builder.append(indent_str + " " + this.colorizer.keyword("output") + ": " + Utility.join(outputs, ", ") + ";\n"); + } + + builder.append( indent_str + "}\n" ); + } + return builder.toString(); } + + private String variable_to_string(CompositeTaskVariable var) { + if ( var.getMember() != null ) { + return var.getName() + "." + var.getMember(); + } + else { + return var.getName(); + } + } } diff --git a/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java b/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java deleted file mode 100644 index 91c5b68..0000000 --- a/src/org/broadinstitute/compositetask/WdlTerminalColorizer.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.broadinstitute.compositetask; - -public interface WdlTerminalColorizer { - String colorize(Terminal terminal); -} From a3780407ff282234b8cc08eec00285b52cd7dbf8 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Sep 2012 10:27:43 -0400 Subject: [PATCH 076/140] Completing the syntax highlighting and formatting functionality --- .../broadinstitute/compositetask/AnsiColorizer.java | 8 ++++---- .../compositetask/CompositeTaskColorizer.java | 11 ++++++----- .../broadinstitute/compositetask/HtmlColorizer.java | 16 +++++++--------- .../broadinstitute/compositetask/NullColorizer.java | 4 ++++ src/org/broadinstitute/compositetask/WdlMain.java | 21 +++++++++++++++++++-- .../compositetask/WdlSourceCodeFormatter.java | 2 +- .../compositetask/WdlSourceCodeNormalizer.java | 7 ------- 7 files changed, 41 insertions(+), 28 deletions(-) delete mode 100644 src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java diff --git a/src/org/broadinstitute/compositetask/AnsiColorizer.java b/src/org/broadinstitute/compositetask/AnsiColorizer.java index 3448399..e291203 100644 --- a/src/org/broadinstitute/compositetask/AnsiColorizer.java +++ b/src/org/broadinstitute/compositetask/AnsiColorizer.java @@ -1,10 +1,6 @@ package org.broadinstitute.compositetask; public class AnsiColorizer implements CompositeTaskColorizer { - public AnsiColorizer() { - - } - public String preamble() { return ""; } @@ -24,4 +20,8 @@ public String string(String str) { public String variable(String str) { return "\033[38;5;143m" + str + "\033[0m"; } + + public String task(String str) { + return "\033[38;5;139m" + str + "\033[0m"; + } } diff --git a/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java b/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java index 844fdb5..4d6ea8d 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java @@ -1,9 +1,10 @@ package org.broadinstitute.compositetask; public interface CompositeTaskColorizer { - String preamble(); - String postamble(); - String keyword(String str); - String string(String str); - String variable(String str); + public String preamble(); + public String postamble(); + public String keyword(String str); + public String string(String str); + public String variable(String str); + public String task(String str); } diff --git a/src/org/broadinstitute/compositetask/HtmlColorizer.java b/src/org/broadinstitute/compositetask/HtmlColorizer.java index 3d17a0f..c47db4c 100644 --- a/src/org/broadinstitute/compositetask/HtmlColorizer.java +++ b/src/org/broadinstitute/compositetask/HtmlColorizer.java @@ -1,12 +1,6 @@ package org.broadinstitute.compositetask; public class HtmlColorizer implements CompositeTaskColorizer { - private ColorTheme theme; - - public HtmlColorizer(ColorTheme theme) { - this.theme = theme; - } - public String preamble() { return ""; } @@ -16,14 +10,18 @@ public String postamble() { } public String keyword(String str) { - return str; + return "" + str + ""; } public String string(String str) { - return str; + return "" + str + ""; } public String variable(String str) { - return str; + return "" + str + ""; + } + + public String task(String str) { + return "" + str + ""; } } diff --git a/src/org/broadinstitute/compositetask/NullColorizer.java b/src/org/broadinstitute/compositetask/NullColorizer.java index df146c7..40b801e 100644 --- a/src/org/broadinstitute/compositetask/NullColorizer.java +++ b/src/org/broadinstitute/compositetask/NullColorizer.java @@ -20,4 +20,8 @@ public String string(String str) { public String variable(String str) { return str; } + + public String task(String str) { + return str; + } } diff --git a/src/org/broadinstitute/compositetask/WdlMain.java b/src/org/broadinstitute/compositetask/WdlMain.java index c65cc2b..220057e 100644 --- a/src/org/broadinstitute/compositetask/WdlMain.java +++ b/src/org/broadinstitute/compositetask/WdlMain.java @@ -9,7 +9,16 @@ public class WdlMain { public static void usage() { - System.err.println("Usage: <.wdl file> "); + System.err.println("Usage: <.wdl file> "); + System.err.println(); + System.err.println("Actions:"); + System.err.println(" ast: parse source code and output an abstract syntax tree"); + System.err.println(" parsetree: parse source code and output a parsetree"); + System.err.println(" entities: output an abbreviated view of all entities and which scope they're nested in"); + System.err.println(" graph: output the set of verticies and edges for the directed acyclic graph"); + System.err.println(" format: reformat source code"); + System.err.println(" format-ansi: reformat source code and colorize for the terminal"); + System.err.println(" format-html: reformat source code and add HTML span tags"); System.exit(-1); } @@ -46,10 +55,18 @@ public static void main(String[] args) { System.out.println(v); } - } else if ( args[1].equals("format") ) { + } else if ( args[1].equals("format-ansi") ) { WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(new AnsiColorizer()); String formatted = formatter.format(ctask); System.out.println(formatted); + } else if ( args[1].equals("format-html") ) { + WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(new HtmlColorizer()); + String formatted = formatter.format(ctask); + System.out.println(formatted); + } else if ( args[1].equals("format") ) { + WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(); + String formatted = formatter.format(ctask); + System.out.println(formatted); } else { usage(); } diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java index 380dccb..cbefa57 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java @@ -44,7 +44,7 @@ private String format(CompositeTaskNode node, int indent) { if ( !step.getName().equals(task.getTaskName()) ) { rename = " " + this.colorizer.keyword("as") + " " + step.getName(); } - builder.append( " " + this.colorizer.keyword("step") + " " + task.getTaskName() + "[version=" + task.getVersion() + "]" + rename + " {\n" ); + builder.append( " " + this.colorizer.keyword("step") + " " + this.colorizer.task(task.getTaskName()) + "[version=" + task.getVersion() + "]" + rename + " {\n" ); if ( step.getInputs().size() > 0 ) { List parameters = new ArrayList(); diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java b/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java deleted file mode 100644 index 13eeab3..0000000 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeNormalizer.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.broadinstitute.compositetask; - -public class WdlSourceCodeNormalizer { - ParseTree format(ParseTree tree) { - return null; - } -} From 036b2294699bee6a6eb881b85b327db33e4198d3 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Sep 2012 10:49:02 -0400 Subject: [PATCH 077/140] trivial bug fix --- src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java index cbefa57..f7e6184 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java @@ -31,7 +31,7 @@ private String format(CompositeTaskNode node, int indent) { builder.append(indent_str + "}\n"); } else if ( node instanceof CompositeTaskForLoop ) { CompositeTaskForLoop loop = (CompositeTaskForLoop) node; - builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " : " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); + builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " in " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); for ( CompositeTaskNode sub_node : loop.getNodes() ) { builder.append( indent_str ); builder.append( format(sub_node, indent + 2) ); From e3b3bf572ae2252acafd261d2fd4b04083edf7e7 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Sep 2012 12:52:21 -0400 Subject: [PATCH 078/140] minor bug fixes --- .../broadinstitute/compositetask/CompositeTask.java | 19 ++++++++++--------- .../compositetask/WdlSourceCodeFormatter.java | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index 8b0f4b3..d70ae57 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.Set; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.HashMap; import java.util.Iterator; import org.jgrapht.DirectedGraph; @@ -39,7 +40,7 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { if ( wdl_ast instanceof AstList ) { if ( ((AstList) wdl_ast).size() != 1 ) { - throw new SyntaxError("Composite Task definition should contain only one top level composite_task definition."); + throw new SyntaxError("Source code must contain only one top level composite_task definition."); } composite_task = (Ast) ((AstList) wdl_ast).get(0); @@ -47,14 +48,14 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { composite_task = (Ast) wdl_ast; String node_type = composite_task.getName(); if (!node_type.equals("CompositeTask")) { - throw new SyntaxError("TODO"); + throw new SyntaxError("Source code does not contain a composite task definition"); } } else { - throw new SyntaxError("TODO"); + throw new SyntaxError("Unknown syntax error"); } AstList ctNodes = (AstList) composite_task.getAttribute("body"); - CompositeTask.this.nodes = new HashSet(); + CompositeTask.this.nodes = new LinkedHashSet(); CompositeTask.this.name = ((Terminal) composite_task.getAttribute("name")).getSourceString(); for ( AstNode ctNode : ctNodes ) { @@ -98,7 +99,7 @@ private CompositeTaskNode verify(Ast ast) throws SyntaxError { } else if ( ast.getName().equals("CompositeTask") ) { return verify_composite_task(ast); } else { - throw new SyntaxError("TODO"); + throw new SyntaxError("Unknown node found in abstract syntax tree."); } } @@ -129,8 +130,8 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { } this.step_names.put(name, name_terminal); - Set step_inputs = new HashSet(); - Set step_outputs = new HashSet(); + Set step_inputs = new LinkedHashSet(); + Set step_outputs = new LinkedHashSet(); AstList body = (AstList) step.getAttribute("body"); @@ -192,7 +193,7 @@ private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { CompositeTaskStep step = (CompositeTaskStep) sub_node; boolean found = false; for ( CompositeTaskStepInput input : step.getInputs() ) { - if (input.getVariable().equals(item_var)) { + if (input.getVariable().getName().equals(item_var.getName())) { found = true; } } @@ -209,7 +210,7 @@ private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { } private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { - Set nodes = new HashSet(); + Set nodes = new LinkedHashSet(); Terminal ctName = (Terminal) ast.getAttribute("name"); for ( AstNode sub : (AstList) ast.getAttribute("body") ) { diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java index f7e6184..f17a1ce 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java @@ -31,7 +31,7 @@ private String format(CompositeTaskNode node, int indent) { builder.append(indent_str + "}\n"); } else if ( node instanceof CompositeTaskForLoop ) { CompositeTaskForLoop loop = (CompositeTaskForLoop) node; - builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " in " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); + builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " " + this.colorizer.keyword("in") + " " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); for ( CompositeTaskNode sub_node : loop.getNodes() ) { builder.append( indent_str ); builder.append( format(sub_node, indent + 2) ); From 1330a9fc6876ebb51ed4393c0a8b54e7282cb1c7 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 14 Sep 2012 13:36:11 -0400 Subject: [PATCH 079/140] implementing getEdgeSource and getEdgeTarget --- .../compositetask/CompositeTaskGraph.java | 80 +++++++++++++++++----- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java index 00476e0..ffb35d4 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java @@ -157,7 +157,9 @@ public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTask return edge; } - public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) {return false;} + public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) { + return false; + } public boolean addVertex(CompositeTaskVertex v) { if ( containsVertex(v) ) { @@ -168,8 +170,13 @@ public boolean addVertex(CompositeTaskVertex v) { return true; } - public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return false;} - public boolean containsEdge(CompositeTaskEdge e) {return false;} + public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return false; + } + + public boolean containsEdge(CompositeTaskEdge e) { + return false; + } public boolean containsVertex(CompositeTaskVertex v) { for ( CompositeTaskVertex vertex : this.verticies ) { @@ -184,24 +191,63 @@ public boolean containsVertex(CompositeTaskVertex v) { return this.edges; } - public Set edgesOf(CompositeTaskVertex vertex) {return null;} - public boolean removeAllEdges(Collection edges) {return false;} - public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} - public boolean removeAllVertices(Collection vertices) {return false;} - public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) {return null;} - public boolean removeEdge(CompositeTaskEdge e) {return false;} - public boolean removeVertex(CompositeTaskVertex v) {return false;} + public Set edgesOf(CompositeTaskVertex vertex) { + return null; + } + + public boolean removeAllEdges(Collection edges) { + return false; + } + + public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return null; + } + + public boolean removeAllVertices(Collection vertices) { + return false; + } + + public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return null; + } + + public boolean removeEdge(CompositeTaskEdge e) { + return false; + } + + public boolean removeVertex(CompositeTaskVertex v) { + return false; + } public Set vertexSet() { return this.verticies; } - public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) {return null;} - public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) {return null;} - public double getEdgeWeight(CompositeTaskEdge e) {return 1.0;} + public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) { + return e.getStart(); + } + + public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) { + return e.getEnd(); + } + + public double getEdgeWeight(CompositeTaskEdge e) { + return 1.0; + } + + public int inDegreeOf(CompositeTaskVertex vertex) { + return 0; + } + + public Set incomingEdgesOf(CompositeTaskVertex vertex) { + return null; + } + + public int outDegreeOf(CompositeTaskVertex vertex) { + return 0; + } - public int inDegreeOf(CompositeTaskVertex vertex) {return 0;} - public Set incomingEdgesOf(CompositeTaskVertex vertex) {return null;} - public int outDegreeOf(CompositeTaskVertex vertex) {return 0;} - public Set outgoingEdgesOf(CompositeTaskVertex vertex) {return null;} + public Set outgoingEdgesOf(CompositeTaskVertex vertex) { + return null; + } } From be3fc94be6bc510d365f27d341845b586f1eab55 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 18 Sep 2012 14:44:30 -0400 Subject: [PATCH 080/140] Implementing the rest of the graph methods on CompositeTaskGraph --- build.xml | 116 +++-- .../compositetask/CompositeTaskGraph.java | 525 +++++++++++++-------- 2 files changed, 389 insertions(+), 252 deletions(-) diff --git a/build.xml b/build.xml index d854993..3a7c921 100644 --- a/build.xml +++ b/build.xml @@ -1,48 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java index ffb35d4..29ab0f8 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java @@ -7,247 +7,360 @@ import java.util.HashSet; import java.util.Comparator; import java.util.Collections; +import java.util.Iterator; import org.jgrapht.DirectedGraph; import org.jgrapht.EdgeFactory; public class CompositeTaskGraph implements DirectedGraph { - private Map> scope_output_map; - private Set verticies; - private Set edges; - private CompositeTaskEdgeFactory edge_factory; - - public CompositeTaskGraph(CompositeTask composite_task) { - this.scope_output_map = new HashMap>(); - this.edge_factory = new CompositeTaskEdgeFactory(); - this.verticies = new HashSet(); - this.edges = new HashSet(); - - generate_scope_output(composite_task); - generate_graph(composite_task); - } - - private void generate_graph(CompositeTaskScope scope) { - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - addVertex(step); - for ( CompositeTaskStepInput input : step.getInputs() ) { - CompositeTaskVariable var = input.getVariable(); - addVertex(var); - addEdge(var, step); - - if ( this.scope_output_map.containsKey(var) ) { - CompositeTaskScope closest = closest_scope(step, this.scope_output_map.get(var)); - if ( !closest.contains(step) ) { - addVertex(closest); - addEdge(closest, step); - } - } - } - - for ( CompositeTaskStepOutput output : step.getOutputs() ) { - CompositeTaskVariable var = output.getVariable(); - addVertex(var); - addEdge(step, var); - } - } - - if ( node instanceof CompositeTaskForLoop ) { - CompositeTaskForLoop loop = (CompositeTaskForLoop) node; - addVertex(loop); - addVertex(loop.getCollection()); - addVertex(loop.getVariable()); - addEdge(loop.getCollection(), loop); - addEdge(loop, loop.getVariable()); - generate_graph(loop); - } - } - } - - private class ScopeDepthComparator implements Comparator { - public int compare(CompositeTaskScope s1, CompositeTaskScope s2) { - int s1_depth, s2_depth; - CompositeTaskScope tmp; - - for (tmp=s1.getParent(), s1_depth=0; tmp != null; tmp = tmp.getParent(), s1_depth++); - for (tmp=s2.getParent(), s2_depth=0; tmp != null; tmp = tmp.getParent(), s2_depth++); - - if ( s1_depth < s2_depth ) return -1; - else if ( s1_depth > s2_depth ) return 1; - else return 0; - } - } - - private CompositeTaskScope closest_scope(CompositeTaskNode node, Set scopes) { - Set matches = new HashSet(); - for ( CompositeTaskScope scope : scopes ) { - if ( node.getParent().contains(scope) ) { - matches.add(scope); - } - } - - if (matches.size() > 0) { - return Collections.min(matches, new ScopeDepthComparator()); - } - return closest_scope(node.getParent(), scopes); - } - - private void generate_scope_output(CompositeTaskScope scope) { - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskScope ) { - CompositeTaskScope sub_scope = (CompositeTaskScope) node; - Set scope_outputs = get_outputs(sub_scope); - for ( CompositeTaskVariable variable : scope_outputs ) { - if ( !scope_output_map.containsKey(variable) ) { - scope_output_map.put(variable, new HashSet()); - } - scope_output_map.get(variable).add(sub_scope); - generate_scope_output(sub_scope); - } - } - } - } - - private Set get_outputs(CompositeTaskScope scope) { - Set outputs = new HashSet(); - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - for ( CompositeTaskStepOutput step_output : step.getOutputs() ) { - outputs.add( step_output.getVariable() ); - } - } - - if ( node instanceof CompositeTaskScope ) { - outputs.addAll( get_outputs((CompositeTaskScope) node) ); - } - } - return outputs; - } - - public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - return this.edges; - } - - public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - for ( CompositeTaskEdge edge : this.edges ) { - if ( edge.getStart().equals(sourceVertex) && edge.getEnd().equals(targetVertex) ) { - return edge; - } + private Map> scope_output_map; + private Set verticies; + private Set edges; + private CompositeTaskEdgeFactory edge_factory; + + public CompositeTaskGraph(CompositeTask composite_task) { + this.scope_output_map = new HashMap>(); + this.edge_factory = new CompositeTaskEdgeFactory(); + this.verticies = new HashSet(); + this.edges = new HashSet(); + + generate_scope_output(composite_task); + generate_graph(composite_task); + } + + private void generate_graph(CompositeTaskScope scope) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + addVertex(step); + for ( CompositeTaskStepInput input : step.getInputs() ) { + CompositeTaskVariable var = input.getVariable(); + addVertex(var); + addEdge(var, step); + + if ( this.scope_output_map.containsKey(var) ) { + CompositeTaskScope closest = closest_scope(step, this.scope_output_map.get(var)); + if ( !closest.contains(step) ) { + addVertex(closest); + addEdge(closest, step); + } + } + } + + for ( CompositeTaskStepOutput output : step.getOutputs() ) { + CompositeTaskVariable var = output.getVariable(); + addVertex(var); + addEdge(step, var); + } + } + + if ( node instanceof CompositeTaskForLoop ) { + CompositeTaskForLoop loop = (CompositeTaskForLoop) node; + addVertex(loop); + addVertex(loop.getCollection()); + addVertex(loop.getVariable()); + addEdge(loop.getCollection(), loop); + addEdge(loop, loop.getVariable()); + generate_graph(loop); + } + } } - return null; - } - public EdgeFactory getEdgeFactory() { - return this.edge_factory; - } + private class ScopeDepthComparator implements Comparator { + public int compare(CompositeTaskScope s1, CompositeTaskScope s2) { + int s1_depth, s2_depth; + CompositeTaskScope tmp; + + for (tmp=s1.getParent(), s1_depth=0; tmp != null; tmp = tmp.getParent(), s1_depth++); + for (tmp=s2.getParent(), s2_depth=0; tmp != null; tmp = tmp.getParent(), s2_depth++); + + if ( s1_depth < s2_depth ) return -1; + else if ( s1_depth > s2_depth ) return 1; + else return 0; + } + } + + private CompositeTaskScope closest_scope(CompositeTaskNode node, Set scopes) { + Set matches = new HashSet(); + for ( CompositeTaskScope scope : scopes ) { + if ( node.getParent().contains(scope) ) { + matches.add(scope); + } + } - public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - if ( getEdge(sourceVertex, targetVertex) != null ) { - return null; + if (matches.size() > 0) { + return Collections.min(matches, new ScopeDepthComparator()); + } + return closest_scope(node.getParent(), scopes); } - if ( !containsVertex(sourceVertex) || !containsVertex(targetVertex) ) { - return null; + private void generate_scope_output(CompositeTaskScope scope) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskScope ) { + CompositeTaskScope sub_scope = (CompositeTaskScope) node; + Set scope_outputs = get_outputs(sub_scope); + for ( CompositeTaskVariable variable : scope_outputs ) { + if ( !scope_output_map.containsKey(variable) ) { + scope_output_map.put(variable, new HashSet()); + } + scope_output_map.get(variable).add(sub_scope); + generate_scope_output(sub_scope); + } + } + } } - CompositeTaskEdge edge = this.edge_factory.createEdge(sourceVertex, targetVertex); - this.edges.add(edge); - return edge; - } + private Set get_outputs(CompositeTaskScope scope) { + Set outputs = new HashSet(); + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + for ( CompositeTaskStepOutput step_output : step.getOutputs() ) { + outputs.add( step_output.getVariable() ); + } + } - public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) { - return false; - } + if ( node instanceof CompositeTaskScope ) { + outputs.addAll( get_outputs((CompositeTaskScope) node) ); + } + } + return outputs; + } - public boolean addVertex(CompositeTaskVertex v) { - if ( containsVertex(v) ) { - return false; + public Set getAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return this.edges; } - this.verticies.add(v); - return true; - } + public CompositeTaskEdge getEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getStart().equals(sourceVertex) && edge.getEnd().equals(targetVertex) ) { + return edge; + } + } + return null; + } - public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - return false; - } + public EdgeFactory getEdgeFactory() { + return this.edge_factory; + } - public boolean containsEdge(CompositeTaskEdge e) { - return false; - } + public CompositeTaskEdge addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + if ( getEdge(sourceVertex, targetVertex) != null ) { + return null; + } - public boolean containsVertex(CompositeTaskVertex v) { - for ( CompositeTaskVertex vertex : this.verticies ) { - if ( v.equals(vertex) ) { + if ( !containsVertex(sourceVertex) || !containsVertex(targetVertex) ) { + return null; + } + + CompositeTaskEdge edge = this.edge_factory.createEdge(sourceVertex, targetVertex); + this.edges.add(edge); + return edge; + } + + public boolean addEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex, CompositeTaskEdge e) { + return false; + } + + public boolean addVertex(CompositeTaskVertex v) { + if ( containsVertex(v) ) { + return false; + } + + this.verticies.add(v); return true; - } } - return false; - } - public Set edgeSet() { - return this.edges; - } + public boolean containsEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + return false; + } - public Set edgesOf(CompositeTaskVertex vertex) { - return null; - } + public boolean containsEdge(CompositeTaskEdge e) { + return false; + } - public boolean removeAllEdges(Collection edges) { - return false; - } + public boolean containsVertex(CompositeTaskVertex v) { + for ( CompositeTaskVertex vertex : this.verticies ) { + if ( v.equals(vertex) ) { + return true; + } + } + return false; + } - public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - return null; - } + public Set edgeSet() { + return this.edges; + } - public boolean removeAllVertices(Collection vertices) { - return false; - } + public Set edgesOf(CompositeTaskVertex vertex) { + if ( vertex == null ) { + throw new NullPointerException("edgesOf(): null vertex"); + } - public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { - return null; - } + if ( !containsVertex(vertex) ) { + throw new IllegalArgumentException("edgesOf(): vertex is not in graph"); + } - public boolean removeEdge(CompositeTaskEdge e) { - return false; - } + Set edges = new HashSet(); + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getStart().equals(vertex) || edge.getEnd().equals(vertex) ) { + edges.add(edge); + } + } + return edges; + } - public boolean removeVertex(CompositeTaskVertex v) { - return false; - } + public boolean removeAllEdges(Collection edges) { + if ( edges == null ) { + throw new NullPointerException("removeAllEdges(): null edge collection"); + } - public Set vertexSet() { - return this.verticies; - } + Set removed_edges = new HashSet(); + for ( CompositeTaskEdge edge : this.edges ) { + if (edges.contains(edge)) { + removed_edges.add(edge); + } + } - public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) { - return e.getStart(); - } + boolean changed = false; + for ( CompositeTaskEdge edge : removed_edges ) { + /* Interface says you need to call removeEdge for each edge you're going to remove */ + removeEdge(edge); + changed = true; + } - public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) { - return e.getEnd(); - } + return changed; + } - public double getEdgeWeight(CompositeTaskEdge e) { - return 1.0; - } + public Set removeAllEdges(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + if (!containsVertex(sourceVertex) || !containsVertex(targetVertex)) { + return null; + } + + Set edges = new HashSet(); + while ( true ) { + CompositeTaskEdge removed_edge = removeEdge(sourceVertex, targetVertex); + if ( removed_edge == null ) { + break; + } + edges.add(removed_edge); + } + return edges; + } + + public boolean removeAllVertices(Collection vertices) { + if ( verticies == null ) { + throw new NullPointerException("removeAllVerticies(): null edge collection"); + } + + Set removed_verticies = new HashSet(); + for ( CompositeTaskVertex vertex : this.verticies ) { + if (verticies.contains(vertex)) { + removed_verticies.add(vertex); + } + } + + boolean changed = false; + for ( CompositeTaskVertex vertex : removed_verticies ) { + /* Interface says you need to call removeVertex for each edge you're going to remove */ + removeVertex(vertex); + changed = true; + } + + return changed; + } + + public CompositeTaskEdge removeEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { + for ( Iterator i = this.edges.iterator(); i.hasNext(); ) { + CompositeTaskEdge edge = i.next(); + if ( edge.getStart().equals(sourceVertex) && edge.getEnd().equals(targetVertex) ) { + removeEdge(edge); + return edge; + } + } + + return null; + } + + public boolean removeEdge(CompositeTaskEdge e) { + if ( e == null ) { + return false; + } + + for ( Iterator i = this.edges.iterator(); i.hasNext(); ) { + CompositeTaskEdge edge = i.next(); + if ( edge.equals(edge) ) { + removeEdge(edge); + return true; + } + } + + return false; + } - public int inDegreeOf(CompositeTaskVertex vertex) { - return 0; - } + public boolean removeVertex(CompositeTaskVertex v) { + if ( !containsVertex(v) ) { + return false; + } + + - public Set incomingEdgesOf(CompositeTaskVertex vertex) { - return null; - } + return false; + } - public int outDegreeOf(CompositeTaskVertex vertex) { - return 0; - } + public Set vertexSet() { + return this.verticies; + } - public Set outgoingEdgesOf(CompositeTaskVertex vertex) { - return null; - } + public CompositeTaskVertex getEdgeSource(CompositeTaskEdge e) { + return e.getStart(); + } + + public CompositeTaskVertex getEdgeTarget(CompositeTaskEdge e) { + return e.getEnd(); + } + + public double getEdgeWeight(CompositeTaskEdge e) { + return 1.0; + } + + public int inDegreeOf(CompositeTaskVertex vertex) { + int degree = 0; + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getEnd().equals(vertex) ) { + degree += 1; + } + } + return degree; + } + + public Set incomingEdgesOf(CompositeTaskVertex vertex) { + Set incoming = new HashSet(); + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getEnd().equals(vertex) ) { + incoming.add(edge); + } + } + return incoming; + } + + public int outDegreeOf(CompositeTaskVertex vertex) { + int degree = 0; + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getStart().equals(vertex) ) { + degree += 1; + } + } + return degree; + } + + public Set outgoingEdgesOf(CompositeTaskVertex vertex) { + Set outgoing = new HashSet(); + for ( CompositeTaskEdge edge : this.edges ) { + if ( edge.getStart().equals(vertex) ) { + outgoing.add(edge); + } + } + return outgoing; + } } From e85a64d48b675211aa9e3c2514e48cdd54485a34 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 18 Sep 2012 15:29:03 -0400 Subject: [PATCH 081/140] Testing infrastructure is now in place --- build.xml | 13 ++++++++++--- lib/testng-6.8.jar | Bin 0 -> 1377303 bytes test/org/broadinstitute/compositetask/MyTest.java | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 lib/testng-6.8.jar create mode 100644 test/org/broadinstitute/compositetask/MyTest.java diff --git a/build.xml b/build.xml index 3a7c921..7abdccb 100644 --- a/build.xml +++ b/build.xml @@ -41,17 +41,19 @@ - + + - + + @@ -59,7 +61,7 @@ - + @@ -69,4 +71,9 @@ + + + + + diff --git a/lib/testng-6.8.jar b/lib/testng-6.8.jar new file mode 100644 index 0000000000000000000000000000000000000000..1e0e35f581acaa5c3acdc2feade0f90bfe2c20ae GIT binary patch literal 1377303 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 z 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
    6T3O&uRY}igP8^*3^c9YgYcaXJ0ioq`3wT&5 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
      +T(fA6O6nGQ~H3` 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

      ++^{ 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 (+*}WN& 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%0ACRtG+ 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

      k&s8n>UG(qD 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�!iL3P)-Qv2P0x~?Io}m$_EnTK%hz1|?qMeHv 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≧#mB6j{XSoh%yAa3&_v9Fe^ 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%0DIZr!R3alO90@c` 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 z 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 z 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≦$u#GR!tEP?7(4#uM#JTvOL1hvhDt?WVCZUXXeXq*5x1!JAtU= zs>+3*HpttQPRuZMn!Sv46*iO#`b5aQ@(?c_QzhnL`Rn+g7W!K9Ml1m-es$Y6l8K# zh4_b*kuak!L0U2>r7zd72dv^G-GQ~2lNp@tKPEN;0!=Sl;Q4}r^8%BVtNazTvS`gm zl$MNV*mIA3Ows+6adkt3OI+D1SA&6E`3_xFn9#^=vpy{z1s1@Q2fN!iR2xW1J*`z_ z{j>>9;dfnUfy~NYFl{_7mv6Q$JT@E{TE)bDTf|c;j%mYnwUjnk$bc^V*kdc9#d>L} zWEb2RnJeM!?E6-9T1vy22MHW2*D~bRAL<}D-l>|~J~iidd7$?a&QyR8a| zwqcIAX+|TN_iWQ_*UUdJ^lKTG#+9o@ZA_uMsKjQW>`^C63U!0aTo3mEm)*8 z4@%bDji#tk8}u@S@WW^h3+zmB>9;tAA{IrQbQPM3rvpx;+5JZ}854kZW&MudsahHu zIi$APOE6@zi#mfA_)`UNLpJHc^CqOTqI$oE|86X8%VtoEw4>qN7rhr zG6;mG5uIv+jC|_z4pWcTmC{R@0;hC+}hF~J4F_BxYZW_FOmBh8|J^P9+h zV?)GDAzQvnU{lz+5fjIYII>=p-l`5F@s}{3WDG}nQOFtM(Minl^d3v+#Pl)Hvi9aP zN?VSyh74Sb;gqNUd0MohV4ZF{-X^&GyE)WVNg7IkD;$TA#dO%BRfG~a6=EUO49DyF zNupTH+(C1VjeUC>6no0Ru%KOoB}MDniE=J)oTEuv8#(&B?EVW1tY&xvq~oHVk5gjt zr4_e`;y?kDwJB$AgTS?XI^67y4X2FHr-@qk*oc|QXuw126TsUS&I|-|xbde=&k4ws zi{E46=LZ&gl!6{Csg;@XG4G%wbxf!_L6-ZW8G2a6) zn>g6wkqI-PVHgySP(wDUh}`G5QOAndv-aF;nqTCQ zj9Y)yx{*nI!OHg72s9_%h+VjW4Y{Os@o3@90Jo!irS;P@%|#uznJjR%VYx+h3u*Vv ziurD67gX(5f2>iW7l3uLoD#E#0ACLkbDe9w0PO~eqZ=uhJJzj;acvr$tsq-6b5+1R zpH@ol5y`tXld6SMC|vP0!gDl_i1Nkrg*ls>mHCsUftsKjRdR!XsL@LW|8+t#>vL>; z7(T2Zo>CJ5!5Sr;lSTjrY^ZI1=z(HZw3riC&BBWanRd^K(1D}|z z%LK<2ZR6mlRl~V#S58ZL4Qoz_xgC^;;txUHQ+bJKbSSCtQ*n-&J&*06KD_gkp{a18 zUMRLutiUbN?=dZRu^HXCb_I66mPy%xo`lvdju0`MqVpzGT9{8~9_9EosB5Th6i9

      #bF`q^3Ld%|7>HSvIR-4(dH&Dwnx%-!OfkJ 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ⅆazWq}O_aU+{8dpl3N+T7rJ&WuPiVg~{g#9Bu zI;?t6?$WI*mv+0CaSjVTF~JW7?fMD!;?PSpy>^SDC1};L_v{ph`nA<4NYzjzTkTrZ zqy{w;ibcPYo`D5IpRes$Zj~Uzh!?KEzCqIn(#>)HA~N0HL{@%7ZYL9*h;VvEeoMNW zKYgnD%TjiqN1_c=mQNXHmvC%n!29c-*z;fSlTg3iqfiS>3WzWGn3%H>s(VV8J*lQ8 zJTA*-^|A0o&uM&M`L7KMD1Bhw44$Ln?oDl)wYpW?hyj#kec~MgcVW=6Us91G4fz>l zSB;}}g5QJ;SI3KU9_CQGh?OD;q-Tyw4s*vnEcvaxi+78ZS)v~Xj=DYsf-g~350>Pb3E>yb9aX2a2j<-aTnJGG6d)uAJz(YCq*dt#o~ z5ZyypfWFJ%yj^2HFfo_sdn$o3OV%^o4eb`YTuak)B%DWSQ@w7SdH~J?H5uBfC~$D| zaykw2=j9^>)Q;DRCgvrj>J8MpNYX!}IAsP6j>20y7DXXH|8lgi*Ugg7l8QJ<~ zylg4gP<^GtU=0%tOU88nx~|t-;|T(D6|;|^ zOnmi7PzD?DaAbNXh6NlJNj)LoJSkO^-NGy zWBg_04ErljCW{r}`I~>BlWJeL3(#i)bfR)`jT$!#VI)7KoueKtJ4r^}{&3>@bv7i+ebe?DJ%^shAR41|+`?%o^70EpWYcmM0(3ml7dcui18ob%TsAb~{ub-Nrb z?tM8R_>fyp`1_FOM6e#1C()`ogKZI#Ec|k%KNOXQvqsoA_{(x8KM9MJzT5b$iJ0TA zEr79Zip-rTSw7aNN&tCGB8D7C?uwiWIJG+wyk>;V=qIImhH_1OpMn4*st;$W<{qhI zQ-0xZ!5O*+DGXfeD@6Dg5zu9FfuI7k845-QnIhaO3}!wt6%ErF2)?+=rQ6201uEF@ zN#O&xS6DPP^K{wmyurK~{6`ix{O`}7WC=;8->WdNKh$@if=4!dc&% zqjKEg{Vdk#vPGg#q~|o)lodyMK5&;K>e4JmLT56?vSlPqR?uv6loClksLS!O+x(%u zMbkPn0aCFDQ2zjqK_=<+>BUYN1eJ|wWDl?WBS5^lTa-_DLzmSl5;s~o~$Dr1HiSE_L2eX94U=cz=@Ya zFQofOd;OG~^y#WH++GlOPqJ2WS81DFufxKfFl{gPXE*F;H)O+jYk7uG$KCbti?t@g z2f-!3(4tYAhOQtV(>?Z(pBr4d=#0yIw*}zGjHp`S(t2`{=3Y1BI$t@%{pjtF$dUP1em2~J@(EEa@hV82BA z!1bY{m|WmSYm^SyW8xIv52-4x6xf;3eWP1ssGbMLJ0tF^iztr;$Vdp;2iruM+SdKf zGNInT=W1xCBd zJe^OyJeTkbv=X`ZmSARH!l}%{V7#-=N;AWQ^Jq;*(bl5#YG4)8c|1e2yDLip+H%7g z3Oy;&J{b?fnpa}BGDK}SjYQ>30-SwmVZ=b&q`^4xS$$Dl! zTc+Vn(m%6$2G3Xo@B(%ZSuX7K#RZPUKe_T1?i^uyrvc{}zEq!E7kqu;{*xSw_3!kb zYyz?bjvRgyg0ct4BnXn!Wz)A(D{mMq$| zo;z!k{utYo^>4B-?b+&_-?dGj!)(ESEY1(XLc8rGE5<3hEwv}muhMRRuZ{Z7RgOoi)`7`m- zWN6A)cC4oOeyxR}%W!D5hoCiUI;FUgX+p)cZkS#e+BItGk=yWT>d>u;k=t--V(8S! z$gW`-+BIutWY<_3>X|pvb7+wab_r{)PqfG4?VG>5bJ%fsxR@os;57%NVXeF(Ps(KF z%@m_)VWGu?NC=@b$51p6Ff}84EV%RB{i{D1P4z~FvF`>g{A*u{)m|FexU1tM@L~93 z>)asSnIlr{^=m3qms(g-_AH4NAhGC6FX)UXXYqt-8sE4wg@3v4)G+7Sl|wNRfK~|b zM7}wgbS3b)K;n<`_JqbeO1WU87hRVX%aj$t%n=SSC-_PEacnkL?+k_MNTqPZQaE+a z8(!|rwzya3PXjC%OgD2*poJsk!bIeRwEt!}7dR+UaZ2cg_&qa{E0FsKCLSdY5PJIZ%>RR|pZ?E=tpOPdYuP;lN#WDf*P#B+MwR&hj4bAGL-w{C zdK}hV+@3nIwI-*bgU;3~AY&S|@>Kyav@$79h<)YgI5_FG9FFTxp;Q>O>rb)QWW3$` zpMWOX;&Tk~f5b8TD+2sq#Vnd~vi~gYF0MxQuKxvN$}L&BED2&l+*{ZX!SLBut6lAQ z6VR>cT%lQ6VhLs1o=;TEn-Z6SOkRi2-LLu{K-`OP{oz1d=h*nM%QN8s^#Aq$OH`!C z-D3H>s5~}0kA!!z%Gj_)o##Q}M|qyWRfag}prCu)vJw|g^$;PMq@M$plg~solibOB zF48954!GAa)kU}cz}b6pqH29rdwTSf#ueG_fa}Gi=k(e8RDAmAIef9`#_QH;nLeNq zA@Kp-ZYiza9dCR3T#apyNn0|D9VKVir1)Z}ge;xEV4PFzE`532D#{&&jNgpzDjv~F z1_w&6ebH67z6!>7Y?0jFh1%jI{#qMm@hdi6CBvo-@koz*gB~7d2!}zfiLuw|VB>|n z9MtdAl9ES=>>4aqy?@naLqnbC6CTq}yh%qIByFGG6j6d1s)RZ#C|2G4_v*VpvMch+ zDwQ>+@qknLfYfu(5sj=%P-@c1%lG~8uA*^ig*Y|T=awgv2&*U`%_~p;H@)#GguelT zR7HfZHYneF31nGkOD;UtC}iVjkg}CEQ@RrF1nG*BZ!i+F{0l>vpSyRT^3mtFMJP-8 zahScV~)@Qj1zaE*PnVVird;j;s` zVT}ElaE3vga0U?#Sc9;7tUmZXMqiX&)*i4uW?!5>lXrUG`Fp?jpo55elHr5{yI~$r zX6n)>iogGtJz8rs{N)B22&m^DM??OcRu;!J%(NgR zC}nh@2s#O6q){W0tq^izsMyL-Vh<^3N|uv(a6udOW}5nzb#;Z^j>@9;Hb|27POEiV zSKFp_wVKYBwT;ftrN-==z*}$DOwWwS_1hPj$F2A6-|MqJ3jWSBe&X!8yRQr4x&_ag zeCduM2@GdR@1t+tJPOIX1|Wht6j0w^1XQ!6aS70hffNv)&OkYaRHy75*mlrUHWzT|)k7-Mp*~5ju z^)ZVmc|O8Dc+%t;5Sx=|8HZP=Tx7e?M&cwqgNOAt8AUO+1N?&a?%_!$Wzp*N4s-k$ z*C0*rbKaPgfE^GgqC6#J;XoA0bZv`N>m{ zZ(jz({S$nj;!(_ZDsnQ;yNvVe^pdYwcD?iyn^hnEth`kp(JV)4r)IWH$wxZtUivA| zl5W+58Fqli(H+wVItRT$OJQf(HbX=;8$!kTu3|WdK zEeiXBt4XmS>}Iltyvp`%epUiLr}c`q#^p3*CN<>79(Vi9Cdz$`Br6Zqp7HvUdmSx8 zw7I4QOywqqSn zu>=-!=wA>>mNln1vIM=Mq(wD?_=Vkb4kJUqS{w%CjUx}Y8Sz$;gw_X5KaogXK?SPnD()cLpuHuLE zL6$$a6K!G}d?!h-uVH)>#z6T9RL&EnqE4Cay049%2vojlmt*JcNo8@OMYzr@t@0<`gcAdQ9gS8>T5xPDL0NP* zu0~c4!H-H)-t-Kk*`waXT{voDTr#$|(bZN;0*uOzZE=yhuk&edB!ln~ckh|i$e%uQkj&i)~AoEqS zSASwBVeG~ur7T_mT$y$yBG6&nKC%7u%Kt8mV;j^xq4mg=D_9C1(YWQasLg} zIwN>wqa+O<@y)G2xnk|pKf`$!kDMV2y7EPNv;HQ@bvWI@-Ya^leP+lFnCW)wi}NTx z1veCBDBlBA>;s=3e@s@6##Yf&_ed*3W%) z7?gLP+vnaPRf55^6NDtIo&7vF&Iz3O7^Q1jvYB_nITKfZx&Fc0L(p5-Q$K^S6f6%2 z*6>cmU%KG`%##1QDCZWKK)CpBkbFh5!cXJDPvN1y7Day+HMud&Bgo(rIHPd&PtH%? zWpMS+<`-|9VbCZH@E1>(hh9LqXK?dZ*YwZQU%asLhGd8nq5lqDap4x2XR!Px#-|sn z!pJo^v~m4|_7~eqd{rs&VcHi@SPoad{)xtz!@gCypmUJ6aM|EO&$CkH`}YUOPzeLy zyQ)jOl<(q4`*+n?z0h=6rS{q0!=0PIUN*-&0(XB@xPCdu{{38*wgtg2*gLGiXZ3b= z%kT6#hbIEJKPdgh%Ybi-+`mHsVSg)A?OJ|I>O#AU9xb|RxTnr;vF$WWcoY)&GgK>I zNuloIwYMTvyV9n(}wlWea}AfoH^qLL{kr?0B!pm~7ID1okP#2-2Z zO>Wqzb7GTP5*a)T2DZp3rTsx*I%ZP;M3Ds@L6)*0{h}pWMi#RUnYAESaw3L780h+J zJ6zJL>8I6b36}vq_B~`g8;gsoNP_4Zt<5%i7Y(l@XwnB+i>F*uRS(%bEONr*T2_Iq zJDKO2;Z2Bp{gb5OAtR)`Nrh(TMO1-138en}q>pO-*x{>6FqIDFC0<)D+Drwkau|TF&Mw zHh{!YAPU8SdmYJ#*sq%iF{`AIlI^B=)8ESIS=Fz|=#g087ThJcQ=<}~w>YFd-)x!h|FA&| zyT9t$bY1ULUfU+WzBv-+1~d@s+Ga%BJ}N4X;%j7wiS)*&o24XgHuDm_>fr0EKO0iT z&ZKWODLL@rNntFBjXaZ4mm>OQ^#%XYh^h!3LQRdAr z==_}MP2laOBn-*sUy`=y{CCS(cvXE(POFxOwfH|W-4r#Ko>_F|gShP`w&yFlJga1} z4mT`fJZj+pO3T^d>z^XNe^^1LgPb)e7Zga$d=jmWXf--@$i+{{w@>i1FmnO-&+yx8 zJPn}N=^;Bz9x9{$*fIK&f?(rm-LH%9{MilYA;VKUAtA%ld?6uGCmoh1ofgGxVEi<} z5}_^p+)c`#K32*Xv<{sZ*Z8BZcwscv(}P>b$Op~&WsE0rZ%ZpNJ=;9@IXTzG#dJ{M z!>68`{8gxNsnl_{Wlommidb@`&Q&Fis$xf#+3@Aq*)rpaLanIfCKtTf@joo*+T8Kp zR_HrI6a{PfatX^(&mgOXK)E7+i#iq0cwd)%@kJ;eWWVPMz4ZlQJlWVN;|yen1@AaN z@%7|^74u~@1hM?Jg{m*4yZ+T&UKCYdd>w-o!K~zr0TaFh{~)?FKu&9yc);B^THn(y<$*_DA!mstfp_i#y$RCD-JZ^o-(TD$>t1#iZ* z9;`Rz+(5aYpg|_ji#FXh^ETFn{gE1gYA!+6dRI6%G!n^pTo ziQNh45xPFMu%bx99K)h*1HdMVUL3LHb(onB`gtY=lgtnoS+KI9CVTbU$C{z{{G$U= zhNr+Cp*UBbb2>G?!DwV;^$tkn3gOHJGuw0}*ZVkzarAf}1P zr4+nGRdOkgtDwC;E49FO`L!2$?wt!+WRWS#QG-RWPj^BBThPWl&~;64Y|n8w1<$DI zGeCYTm&8Y0Fx~Tjrjy6-t5?lB_c4ush{rrNaz1hX;Cjdj4R{CV{R-GXG*tG1UYXJB zAE-nAs4<)hCK%@o?1iWbra4$Z9H1)OI`a%i)8@TP&l_##sa98*K+z=|vQ#=4Tye0O zAYo3kB1>KMv5L!@{}+O06n#jwq=Nc;?V|}bsY4Jc$~JfX_fRWl9`@tQqPLA>c11bYTQ}aq4 zOZk?EW}Aeqn2M$lT-ghc5IRK_?7AgkJ`6c-B`Rr;(N9`r&L0J&cN6IGOg_O}Ly9 z58sHEZHLWxvW*1L{qi7j-o2Ud(i+W;C#2Qdj7b?^b~tZW)WuyLtUmt`YSrq@3$IwO zOeGaMo6AYQRjnEX1ywZ|h9etr^_qL3FWU=>hIw~ix?6NP%ULM-LOsv^8in$E^qPj2 zygN!YSeo{~a6;rBrhxz_h)PQ7s$pgf3FU9bZCDF z1yxyBl7f4*BVi#Oz$l?w#d9k>*8>nAL>wa$l^1rd3f;9JCYzN|)(+;}3$9>z!u=#T$IZ~)!yKFlFVxcPvzqS9Y9=A zzKhcFCCm6q1SP%g7t>?I3rwY>FS}Uh$_Etp)3nNmWaqU@!>9>Xw!XR8Fq}YF1Q_1t zQ^L!E%?;E;j@h8$w4a9FDm^J2^TGCXMhrqc7rOQ7tAUB~b0rvej{oWM#2(L65|!2L z!}TQiLAW-k``eC^Q|rz-j~@1vM3U2d?WjM}n1Q?hT@Q99@a*KodCSMn$$$~|1OnanKWOQqMKeso(pu{!IgJ0np>F#|R?S9mrD zuKIsbx!eD+S^EDUfZ2aWj{di@IWBqLepwK4tlutYovo}Cc&dL%n2Kl;cp0Zkq=dSt zDomsbI}LxMM8|@rIezV`4+BFG*AoaInn@ls8Wq0vIBR3id+cfUwti2*A7p(L1_S<< z$8-OX2*0zT@nF9(L=H!XJ&$pPTUlz^tb$dC0#==Y2L-k|N%he0!He=4f?qajrPy|4 z8KuswGf!wb)@%+4oIzFkTz~3G7tu;0OWv2nxft0XMyf1sp)+7JA>JZJziiH|sTqfn zcAQyh8#SByRt)1i`711`GGOA#DPMtGgYra`nq9k!G?S!|nHY)tT$zYt4w?@cqUqYs z@4$j#ns(_`J#LA%oZHW6Y$GeK96$XaIj8uCv#s&w0Lz`1S0ZG6&>u4?W-m+vcJ^w@ zSW^daXrV*@bMM$I2=zOBn+tfd;!f@ zMCIm?TJCt@1+&t!^gh8D1F+tduWL0f8(v*D^CmD4ij6Wr3?Hup%edvo?+Z+X!y z?@n=@(x00dQ%7CE--Xz152nPgP0bTTQdC4$RQ<0@vFD}yyWhbgnIUCkFX7w&qwk~t zt zv{hC%6=JQZSoAba{iF(tPMuuk2pVfUXHEw!Z#(A@(I<&Zwq<3TwGM47YvvuAMd33^ zCNz~XW~Hn?1TOJdJDe!9G*NQ8Wdzbo^Ac6s{Djys)6YWD-q=Kf>El#m{is-5HRmKG z$J>;1*s&;#B8B!Kec8;8a3?*JBDP{Q|;aZpeLUJBqAzW03e+MI9QUu^fZH)O}Ns=!u zuCr(1i*&X)_GOOUOg!^MB#*K^`26%90kINcD2b9U6Od|;L_LUdClNGPCh)9S5@8sb zDVstCfM_|##+oiUp$`z?F%&o2(&EixWYHoZLi{0B$_HF*|D;f6p)(YTMsMhv^CHEa zn0iO2k;HJuppH1+1h_*!ND@y%1_+tvB<^KTm}8w-ZOhPHF`3#KRr6%0>to4R!nKGK z)+?;3R$Eyj>oEelo$P6#QblK%$k|MW$=3`XJeja?63AjMWVy+cQqKo`6BARcz!_Y` zb14>+H&nYRFq=W?=U5Sbk4>Dvi-BZ$?Ac1Kxi?b*Sf((SP!y;nop?b&C*DK#7Z1a^ zwN|autuJ1*l>tlChKAg!^h&U;C1%;`#a5-PHX6OKac=O%U4>~iU5ywT+?7Vp73u8O zD*!kaVJzM#VWgfozgC7fk78NxFKqtu&pBym)K4It?I8dpeqmGS|Gd zMW$uxfHK?agtb|#u}m(wcVVe;OSwAEbEl#zT~rU}CEMOExx&P8wnMZp$y>_=qyBe` zYjc+h3#yxim`O;JzB0{GRUwNlir*SNo;E~^n~5_fIIV6=A=_nmDc0$In<}#fDC`PU zZrs{HiTO#=G|AXo8$KB*h1{2p`vi#W2q66Tn3kiNAy)PZqu zsi!9md>-3)eCxs6k^YFjad(hS-=PtIS!9jHY=&qD*G{7%61sE~!Oc$0H-slM9jz-zw=5BARwRmfLU{9lJ zBY-Zmo+B=Ktm@aYseEzH{4J%ZLvee=IWx1cE0@l$tOL{{f7`XiG;kZPsZ5%+|EEpl zAMt<;%ZD6rVbdELZc&56>a0o|;b(-;^87z&MFGnJjQ*RgvXONKYDC^NwZdlt-D3v5 z@Sm@T3^~$a(J+ghKR|ICAj8xD||uLtR7qy+pO;;(9MV- zoVrcTyDIi)?nKD9**VF?OJDA)!0=S=dW6gvgt`=wmc#Eb4 zcy5??Ti|@qZ(ZPeaR0o(c`$s$d%}BcUfLcf2$0je$@fmJ~)tF$Zuv~2arC=0S1V8NKcmg$iU(OCgAZP2{2yp9K?I{{aO%t zkn&$S;By^^^IeC2VSz3KUcfX1V898W2DJNj16yD{pzmoQ{%H5rVBgsLMS%t|HPD_E zj#2|=hH?Wa11TW8U^OtF9QR}(b&82`PW#;BaQ6lhW2}3>+J0^S%0s@t3VMU|WVpxC zJ!5do4LGWKnm(5c7MQ+I;6MoI+umh*{fK`<+f=4kio-QwbWgL?)^x<9ikgGXQgmvZnNK^;pt0j0> z$Z{@n|BQ0JT|LmBz6%zmC?n8|;~RYJbK%!^17o-Kl%Q;QE)G3cyjAfv(Go;I7YiwU zx}3%v3e=m=Z%EUb%DoS=7`=?T=?^+9AO@3c6CuAel=7bIv38)!@PZp|$w4P{9AmfY zw-VI~ZJq1w)b7`@RXRbg9V^CeRb*Bsk(Yl$t~^#!v& zE3)6%auR$yNjWdxM@>5kp1p+p(afwJZs)f9F?HAGaFYI8@9yQr#MyZ^S9}ehP_Mm& z{dgA7CZ{u)15Ombg2BDx$l2UPZeF~ujKT9%L~mZa z@5WY=d^^e8!OV{x?#4JCR0D&I&Tnb^unCXUbld}X^KVa}tHKMP4oIHmGlDM98z${T z_Af$sKGMt=1;ERb*YF|VHC8|d&z}gsqrX)i-+J~E_=8yzTO<8@eUVqZcn{rpUNg%{ zB)jqNJMp~nED9}7$ALE!FS}i)?R6A|SC#Bt@S9!n-r!{2A>NxLlvpXFUPw9PaENr= za(-J1i%TY`=UV0l9i$yC_+Lc4cxRsq1<9BY0@?3YA6Wl$dIM|r%$S4+0-_}Te|TX2 zO>Zi$&Q|so!fxi~X8%M?F9#0~wmM18DaJ+np6?Uh-@n~`Z@nKw2>gC&k!>y`a!_5jMe|*ifpr;6kU#0d z`6*{-de2}So#$P`2CC;W_OL%~toy&m{qzJQ_j>1OqV7wCRaY^U6z7ib4X z&*C8f>MrfF4(jgZA^3%T${39$f7lN+1ggDihtzZT?Wy^0ons76@{OWr`NGb@p`L7* z9%!#@-mcb7>>BD?(XyOKr6?tLZ-$keg@(u1;_g9I-k-TTe=k>9_m{%)mLd{#xv~~Z zYf+eTH%%gDrYwFxZ3V;M#1%hdus}OWQK{^FsY}6cEVWa0GUdVt+R&UzgsS#S$x?ht&_eBVipl`kD-~Ja;K~vIGY zE>X=WqbGM}brAlLCl^oWW@_mKC<1de^I>j?1%h6dwrno&n| z=x~{6s3XQg;uxN-h%GYp<&+IDDH8)$vum3CHI-Kr@DvVP9d0S~a^ndo*=js=qb|y# zFvpoHyd8#4DH++LXH-%OBC_LZAfNGBFC{Cu@LAte{OD2?p>RSJw_6$8u?fg|8AX-BJik`O^Gi3bkE14b{Gs zyI?JJLGa~8RmvidSui&e)l6%2me3&;;YRjpwTzso(qR?16z^R6+ijJ0wG%$t!G5(= zP6#sXyS$jts~O!^2hfzRLi&vQ<5tJv9lNGVwbGJ`6Z_gb+;dER|Bh;SMmzf5a%Y^q zI2rp&77|&7>SxqFP=b}!LW=tNWr>nEqxE&FL^b=fpQe4OH2o46Y7a*W@9okhmQ>|V zz#Z60Fz}|!Z&eLqq!2J``0+!h3dM}<#VdTtk&<$`yPz4GtHjC6=gtm%*$WlKGbH{3 zX9PdVlMr9Y6Md%%8N{T2eCr7?t7}l6`-72}zjA2|G3)i9geM|48o+pI^aWTK`b-UT?9)EEAq>_RrwSHleDvUZ~HIddxl&i3aPm*FJpeI}{ zQjK4l)vK_x!gIja2V`B%UTbxy7AKU&VvmIVVg!=PjQ;~UMOY4F6@$lNlL`369&!9f za@f>^o7R9_km?ptVs%>;jz4~Nc&an9sU6IthvK8kCFNrrTS_hkk(@_u|Mb0g!-9ylphmlFyYO85 z@R+xZAQJz2Yxh?<0PO5$?6mv_?qrB)H`D4An=Lbl}>qYIe3KW2_X>CioDJa$wK6Sxf1#*ub`J|t`xfEEEUz9(l zaz2;kT3(6x)p(cg+UKSGl;z7#E--`4m|4|qNuKhI&k{?LlK{wR-lrXTa<`Dr-wV2d z$JwH9>4t0TqKzMQ=lOw^oflW|gt`A4I_d){+0=)MI>UiAZx`7cfx2k}O5YkNL$|Mt zbN?l~&sBp?RNdRhVHx%tfes{}tevBwjZ%c>N$o;#3u=sBTWUw~EO4-cCB~3RT_<*x zy!hE4y;r#S&Hp)?F=1*i^-#q#qqE@6O*^UZ5mt>?WUFqW>PTY(6h*^Z-J)VDyXH}~ zcv5kex3-hKxKquB={n`Z&GLJxldhXlq}`xMyQLV0+DlN{HB^0p@TR~hyQG*M6r9d2 z`1wg3SMm-6)-99YQ0yQSD@^Ccxn_Ry0iG4Sk!r-UZ*L6gyxjJneYI#unt*i}!2p4L z14h*ta)-h6JuNeoUqvtR7rhFed32rPkCWB`%*=8)tQ{^}hPQ&DqUctt9zw(!fK>Df z>73`>|FXD&2*5FIJ-Nn^PZ}=ud7-sD{PP_1OoS>y~17g4(9^o;(2A3!kKB9Xz3z;&!7as*!E7wb0#dCM9w)6d7S@RA8{ zI~D1Nn19iz^#`|@k0>)R~) z(q=x!^J{6?|JK=i>`(T%pA*U-uK@WdK%bA}9N=p2u%a6}EDomx&?&Lwfb7qWekNdP zM}Igo`6OU9M`tpK^!cLY2kYduft?t)H~3a&TJpfT3V(*g{CsH63;j8>%jy}KI%d#* z?6ER$*Qyt-5j7VJ2T4{$n!vL5O}YG9emSwCN`Rm?$eOj~z~Z_z#BFOE5E*b?=5F4cxke$%ltyc)!hZ`B+g^V}-Tg3zbL% zHcgbl0G6Zd;n!o@2fqBm+a7zA1y&}#cDa9lR@k<_!J4d{*MzQc>2=cyQG3{R+v9@R zm2&1V_JPC92H0EenLR6ir>EIMK-O(idAZ-Dci?noG)+aihEgCOdo4EIt+-6J_!W4k zXAF*MlD69M>805&p=`Y-ILciNR<w(H4@(uvyPavuXSCG%+!<7}C zL&FZ?6|8Ef(C$RxBfX|x(O1>H3!_K`G{5*+tiD4&ALi%6JB&`r7DF~_>*{Acx?Hc| zRa^yT;>Bjzg#^sUw~m29W^(J;wNMt@J%WG;zR4gG7QqZyHkQs=C0G8g#nZ-MY0R)* zg>)1SBITAPnh#P8|K_a!<)}*{j#WB?1z_G`g1Nd)ak#yJwyjgqmS7QLP+7 z#?6V9;8Gt)mA*TDss2!T=F_?OVjAWYL-!61n=4+}EKmIFJI@4*+g@Gq2Y4Q8UNc-i z9-Q|mPi5)Bhn)8f%u(xuFZ-+yR_>Eeh%}=T_Chkb9La@Wq$y8^^@kR3%FB4{F_fZZ zAy@Bw*TF*#9Yjnr3zg^zwJ-gyL!`u!LCsk}*dy@rgVE~)@@8Mi`h@86*y!@C*zuS$ z_xR|UIbj3&8I1Fci^R+ywG`khp>{ab1I~iBukyl#DzowH$0q&eCZ1-p{gn!0oa*^X z{iSU$bMUu4S)3{5BW-8&oQl$c4eL#me%ZQ>>Q$6MnMa?vNIf>aL5H3?VcS&UJ|E@} zT*wQ@|6TgX=GkG%{*T4V{^v0GUn5ig<3Q~8ua-jD%*D;tRm1t;()qv1thChG{~)u* z|6YY=bIPMgQ_2?Il=&GgI^M^2Ef(J7(Irp%%QR4~$3kZ{nh zU{T))!sC$%pCI5-i3h0)htC<6@5Jen?M5;_uINY=Z5Nqs)!kL$g=;^6TuDQ~PMR|! z!fv!(#b_)_DNOL~K1nvOz<+M@>@ThEp_nO0j01sppL_|k^WldFv*MiXwJj6`&iXqt zA0{Uz{Eg{om3UhBvB~ROF=h+~AHL*8u-h}$WN1tH;JNk8xvuvaFH%@w$;N!^t7G9e zSw`QaTy=}!*Z4n_y@PjUQP=KSu}-XtZQH5Xwr$%<#mpEc+6{AN7x`IOhJNN3h^#L^Lc?9#LU5^4DiGX5g!xQ700y^4C7 zHF4%BedjrF?lBB69~c-AQ4s^bWK(3YCNWsA2o=)C?9G8Q*(SE-60m4ECTl)c$4es` zy3pPZP=7I~JNNu&RMm;ZSC=HQ z)ZdrY^_`$ zrSJIWwQ8~a_`&esv{U~-i}3$!t5s{l_~@uE|2j5H@J#nSWwue)Tbx9eOTW9VI% zs&)zTb9i|s#!7iM#GFw>HG|&s(X+T=4`N8UmJXI)o!k&@Q488I*-jAe zjOA%lc8h%Rgwm(hDe$}6PvhO!yLwtw>Y18^sh3(1U(QMpkL7j4?wZ`)g1km9nC$im zk#H)8{`q*<8GNqF-;+^$t4z|nF?+oi(lGAr>qFNozrD>+M1a(B4(QPb zb8$YB`g<8)ED8Q4F_C$E%qw$c=AP6A`M2$gJ-TY;xQ#U;cQXF^%7Pv%4>C)$u@|ZgNA;L6Yd{Xm_)RTxZ z4yuQ&K!alEA)Rq(xt9f2rgDTtRbfYIH(nG=`56nR#r%EeAPh~47KUVa6VCw8Ao@Hb zv@OEw>LNaJzWAzhyoV@W4--EzRTjIe=%sF23A{YEO?#(({IB$KMF$DRMaZ&9G41^; zqx>eA1S4NMLwRbHYKs<=h@7xYr9W37Q`&DO0$l7H^4=YbJ=Ei79TqDSI|PTYYMk%cMf0z#kN8Ung3J+Nkzv#L^850H<5hOq~7UxtH)laQaFQ zCXlPxgSvB`K4HldyP6P?@t1s5k_0SKJC?@*I4=WO0F?@KMNkwJHKgxv79Q43zWvTMdo z1=cNGBha*wZF*Ts6K`5Qt_-mm^em6&Q3mA|vmoz~*^UqJE3fg?oJzVr7rBgt_iuYT z9($kp3lP+0gTJ)Vnx!iyF&K6T$`BRP^6i}%jrqeP=sR~&%v&v=sxfhD!0`yXv7h?+ zZ5O?tSnK)qAEJH~NRFNeO3dlkSV?B64IJ*=N+$lE{mu9q`$6IP-kAE&=uZFDUe9m* zF!dFk;osKbZ|JpOw|TjX$_hT5Jshv9e$$65rl&YQ3zPO49}Ird*e+G9r&wNp4u9Wo z=<%CUE7?#NJITB;eGaMMca`gS9*z&vAPVEZ3fO>P9-qt0rA&0osaaIHbZUjHAel8dK#4a&HV^G>8`lRF9*9}-J9wB>LmaT< zV~pnCdBL}KU$=_XPuXfSEGsmvTFU>Hwd=9XsvK9o>NWSNBwOW|W0Vhip3=Q> z?30yGMwF+(67J-2WETpL&6tp5qBuB}@XquLs|v#Bh}HJn$f{0Hzm!*2=*Q&#Reh9| zLCsiMSz2P}(BD+)tSM=!FShc$92Tnc)2%MAP>oTiV^OW<#>5s+$bX<(4k860E`h{Y zapj7X%oB@b1tK@#H3^lRFH4n!o`PH7K|=X;h&q1qOE*6k^=&c{TT|;4G7`%3;bz+o#;p!M3yP zE=|W(&0!2ZsHOKPl!%+llw#@^wRkQM8)ZwU&2Y-%Jyz6}w^XX3y6zRJH>Xda7^6wp zBDi)Ar$@;y*BGeg5cz{WaHCI1&-6T_mO^}oJSD5 zIl1C7E+fz?q*4zlrbc?IZdP{4x~8{{N4XKfd}L7P=SfEDgFhr@hwsMCJW`E6mbqQ- zrt&2K@8hy-x+_Lic$VpvFHetsTMcHVwM81L1m9q^J0}14yr6EkiLF|y8dv=bz$`%^c!OEaT zOwwBWKN)LJ0a5POb0p|1S$5-XL^F00cxS{*uDqWg^ zaXFuUrQuIIEsXUXtAt73ttoNa!*rcwjCEfKnYJ7YROc+G>^0A>l_CZj{D>4bbUWsWdqgoqVZ+mvQ=oDq_1Ikj zYZqe&d=%f?lQE}1PSq$rOy!cBYw6RHST#K!m}pS(Hh|@ zS1ku*%zwX^RQ%rmGx&+xDxA4UgfYtv$peYKWM+;)RAvEcM^5T05B@25rt|XmM0oQ< z&<(c)z$IYY%PE;?UwY^c>1ukflJ6ZgMP?Z)lxz!nTD?AMXh%W-H za?Rqq*a_kGuIeXDrJCx+powH{5M_geLVwb^@er>NoiuiIoM)XUA)orpAw`HCF);Xl zOgxkeIcwlyDtNipQq0lO>ZM!Cr|Z4U)VK@UtdEm*>ngHyq|&aMJHM;dRn*R+I+xbM zf-DGL!@v#%=3=x)r0MZOujTQ`pKN$)z5yqnLUnRGYb4hb)i&Pj9EBX>RBNJZy4I|N z*9bXe79>A7RumV*B(01ayc~!>059W-(_u=5kOhZn+tanQXZ;m!D`a*BUlW z=Cyb!1+^iE`Ln@54Q)$st0KT2dubPyL}%9eNjMyA3S_O&R$7%iq3FC7Krfi2liWi} zGFKlLx)$CgAC+dz$7tzjeu?A+x!fvFZ25#|Vc9caJuCV#yiUZ%<@PTp zi3i*;d0C1WTWUg|i>Y}57bt0Qbknu5r_kjD`LZ~fi=!)#Ls+KiD1uHEfeS`1=8!At9-pGC7_FL!DA8g+cjv}#Z z8dB%onMU3&y&rsSJB%%x*TP(ddK+mOYtWd1*TuVr8FLnuYNu525Pae%fKY$)^=nj? z?b!*B+@xE6u7l5u=x67P=Y~0=45dHP%A(J>)$hF2ea=)awFU8WcDT!PXj)?EDsa>1 z7F=KUCFm|p%ZtTLC>>P=_*&JMOrwALmOV-sntB!wk(Q1ynjU+pW7`Oim2} zDnKjyTFK6(S%Fr%u2!W7Hsws53WaycM(IUjp;CTQ@l`nTtf(5*V5B{6%$_iXKZXaH zWPUk@>4}(o2?d=9TC2@1)WrjTS5-iBJo=N48vW`DMiLfvm9(;<~V_wLQ$F7 zhGv8oJH{<;&&(D*qCX1}!N4u>eE!ZHSNbA}joF5IRI^5{`+ox=XoehAH_qP7D@W=U z?DxxYtMtWt^Gb=ln27gM)24?%SRSehm*9c=W?WKiNtUMAlVHbTxG`q-Nt|?}$3En| zn2bebwAT#Q;PWkD+r4OtsKxhXldjNhoeeV!PDK62f7Rop>sUkl;K5<^{Df!MJoZxi z77^c2QAFTy>Mx0zZjB;{1iw&9z#i(lbo-$H6eqV^)*eDQ$0{TP)YQE$0m{z)Y7pIp z-+7(}PccRY2fz6ID}j+446GdKz_DM=-74;JPDid!Vo07ndb2R|sEwaN_(B zyS(UVU--QOwri_@bMZ2HLuSvAcyXSQu9My%&-G%n@k?|$-JAglybGx;j@5<@DQfv|i z&%*MpH((o~J@w}LJ2xU2fJVSD(u!9?E=az~pfJa-i|!;_fn2Y4Q;%RaONSZDN^=?C zWw7l?%_~Ef?D-SnFJAs57dYl*B)kM2l>Am{yv;^0S_@GJzS53B;zaO_bKQb zlGAaRCH!UKvPn+(xEL*XZpTN62kt!bfG^1I)9_wpcQO%{nKtQKnnhn&OS?oD zWC}Esf_;IPoW3V-(CTOK^{c&}Lu2(|9)m6h!uZVyxg+`?my-??TUgx_0QDNI2L|w< zi&u=#jTFId;Fg%d#s+gj9+`vCvo~D&Q217Lf`VJY_vqLV6>hnYFc5=>j)FS1JuISwRG}M0nG1+X6R}3}i zFY+5<8Eha#*s0jGv3;EY&BpPg_IwOVha6bBJuUZ|WZhqxZ=2*(RJ|-6_q?lwv$g_~ zc09BjNYn~Q{JWyxl?X@&Cfx=YbZr=NXzczgE9eab_{PqB!$*|g0KOMs{MeB{DreX7 zfmD5NvCH3Y{P6)$TWszL$2W@iz&m;h(UT!})BHeuUA%KUdP2Gr8B9LbnJpHuW8sA} z-j66(c$(x_>Av%{U?K2H)YPF~xMiH82TmztjBby@MVZpILzQyhp6Kk7*#X2MIuaJR za^=l&=0b$A_=R&Ztby<1lMSCeMNm@8Nnl$J!bf2GYs4qc2P9L+|FGz=)>)2pq+eBB zS94dm`(ba`l*_!}3BvBI*jIXj+>7*=MD~Sqpf9TjOlDW~+l`bMcG_X+1}T0Bonuzf zEiZOJseq-^4|}emyHaWMd!DQwPkg79>4c+LMaqY{Y84%f7YPPmR`ZWKxAg^s(N8yD^nBs;C z-;bJx?l*_nW+ip>Dt3wSX(FV*Xpbdmu_eydc3Xl@p85H28GQ$4I^M~)gN{Z|FIYha zxE=atNKFH@i!L*r<05ZhA;@^#pBE@ZGi_pAC}uh3LGeW$zC_wSZDxv<+I$c;yP<(S z{`ch=a(4bfD+BfCAlojb8d4w#pu9#~@HHtoI&>U2;QYcAkEEZ0Nirb5Ut5hbF)gZpnsY(jwQPb5131 zE6g&U5cloW57cLXWgSidPX2vn#E4U_@(>WEQ=ZEP8;-a9XC3XY$#;KjLHeDH)Scqu= zkL@zvFk+4u^Lrl$yd6o7q$e+2$7~5ojxdV{Jt1=}^{bD|P_qA+ka{kPzh$JIHmoA* zVzq8|rTqVR3S$YLGAm|PPYZMK_nezU7j^PR-S6v<#lgLythU0 zM;g`TW^U;@z^loNvmPyw7p)p?sWX&d(9cJ7fSVV(FnIK_J%FstLE#G1(4)hE2*k7c z$164b)1KftiS>N_uNb00sUvMC=pR4Mzaix$|4kb})y2~0f03@5)#1F+)Uo``8#`In zWZVV?^5BY&{?w(?Qeh$|#9=E@OQ6681pA|tXA;qF;WRet6fJ29YBN;37weU&M!V-P zlc7a5Q!i^>zaf5L^2fg9G$s-e!3`hxhlQnIXMN5*`|Z5z&KzF;>vDtdv-)5Orq5El zRe|QuLdZuYKwenH=BLJ(4IdpHn!$oM7oNNQp65PyQx$s5>cbo?zqd%uk2-*x_2;I` zqc?A_5u2aFIY%4>Px=IM;St!qwruX+lR=YJe$svgQP(( zv7fK%;H=O~`%QDfenVgf9nTxuPhasVV>9nRQ?adx+-~H*w#x}ulgG`o?9PVvg<(Is zLztumix?7HAt%}uC%0{ZW^|5iaqNx4CE3W8#HKBTl&(=xy^SUifbi(srd@WX$OGn6Cy@G=AOb66Ijp0DT18K z44lz_Y4Ot`LVuX=Tce`T4{6ZR!GY;(%$~X02W5e`-bd5flK2%3b(7p$Gpm1oVx?qh zctUtz1wb|5WK0oX#y-ka)-PX!s!q!In;PUEdP_f6+fN?Tb#hpzNDY|WHzj_WIfg8u z=spFDnl4v=q{H_bKZGZ{m9g5d@7Z1`FH(hD;lKT2Y>*#P%4Gm(j1Kb}_FpOIF~M}N z2}Mk1Ker)(>&#IXPZP(q{y7=R@WmWEj52LNuild(=OOpjooth#($G_NUj3}mx;9jv z0-4MaGxznfN>qGa5K!knM_8XT$hRr27H2UEWS4^b2B4}Ve zwl4aNxg$9%4%l>#WGK<6yMX$;t|@!fkV9DpU@!Mh*pLea2`V~^x6*Yv7@On{4edqN zmekE6{yqH@>$zSZOBpST0IK2xb&o`h)FP!VYQO3OLWC0!wCj~yoDa2OSG>`il*paa z7ryO3w@_V$`>|QjY*Ol@xi>)Iuc$COT&0w`J=sah@PE483wh5{tw34Apq?5x2AxDVSTa=M`%Twq)qFKK&d+tQiUK`Yss|u)M z%3s0)Q+T$WSv+c=aF8od1qC;BmkZrHE#wTTUGI&WYq@9Gl=Ij}&7M88ve|3Zl%2?d z+Q81gO%hwh+RE8TMw^-}wvQ&B)i!OFaNQ-(&StuRXiZ?ZU{up|dZcE@EFHdOR((Hv zdOl0_YxG(t?e?IVrT;QU)%Nx4V&xS7Q$C_f*}T^6U>OEwey-q#WQtMsME65kSPS~9>(i#qg?Qi7Ff_h#a?6? za^*w?ihR*e^dn{vY3p)BycW>3)gWfgJ6*xsXb>N`4@>H{tNeru?|V*q$LOul<^i72)M$j z`GQO;L{!laUDQ5ozmM9?6i{I$I4a*c*#M%%y~KrsmpESQF_RavI}l8+17dOT2KqSb z0lT~fv5D+O0}_0jp`aL#I^+Sj$wp+vr#vX0zXPGANSIMlUCliNVk9_wa^Q%_e?><0KOS;H3D1_a zG0xruonzdyaFLOUnPQ#eBK7if1!YtnXf5+sHM($NT<~;D2;_U82+y7&UVS4c&hWrp zbJ=CE;&f}rJDYtvrazmnOYZ2EVw^J@?=bHQ?ost`yi+M9HK}uHtbZI-;N=aprIlNC zYO8BFT3G24&s~>YyNWG~b$UxXfGw=e6OV6a9sFxb{oY|Pb@|@=Bd z>Hbb2(L4;@33`D9kv%IYU_TR&;rXYX(p!(lQ7Ar>vAwxSmQzr#O zJ5!tg6$Mt^P}>kg+d9Y$R$!!z(J1)4zSZX$D^Ba5yeN6nmQSm5 z_o(Hl;!Sd^p?%=Me+!SvxK1)1BJ-bem=$_;n(@3zS7v0pJ(v>s!O52t$)>gA*_p$g zfOOAqdt&9l5zV|@Hk7s77EzSyBX*1P3PSMuH8zWrbTHr;fi$O4Hx;VYHuVInfrlDl zupANEaE^m(&qk6d5^79Ozvhn#;pTLE+48<%75^t~6-%@`l);JZ+Q8nlCxa6in6?ok znpJXGJc;VW#*=dA{;EhKVR8dwMJ-Hu1BaC!8tY4eLgp7xg@H0FB9T)xA!DB^yJuEp z*n-ndVt7(|mSM%%f$N61+;CY0-dbgAu2mP(IfgX`vYzse;Or(n%FP!a_+_{p3b)Z=SRi(IADQWyal*a zW<4gCvhULyJvL^=u2&Vu;Nz67B#FSB*|nKU803mZg&G$l+B3pny@S$Au2OkIEaF&D zD`|kh4bAj7eDD2<4g|$!CA_6U{O7dLfhh0)EAC{H&{DM?lmL>NN<* zu*H4F(mX$zxUvl7#we^hh>+*H&74qZJ4l~#ph$2iXXk(8m~@;#;0zXgFa-6~Df$;| z379Kvy&=)mH-P@7cvS(ap0K&Cx{DqeOw@0Y7koeT^0Sfh0CXW3PcTFci@W!yc;?4{ z@f)QX_Af$y8{X``FB|_`)7$^twa%up-;TF$Ldv)0?LT&Jvg(FAw&>4)vTYZTEtbMH z8r8)k!O~QEh3srr1~kdn!+1|KLh6*&+2{@u5Xhw|9G>?!k2O5`wTpwn%8B zr{S$psp{TLi>74)c}i=gne(Vi@cMI-;2ILW@RP_c+u~7(oHA@}4BcV@D4dK!<_K(o#4Rb94kmsO4`tJgSU#`0^XuFq;6d)`2>Y4pu-Y zcXP>UhiIedqb!9uP~X$j_g#-j9bHIVuYpG{Ss&9X`krLOMbr>WqpuN?zrPflpXG*2 z1|A(ubqU~b!7PLDC}F!a#6Q^HuSMyusw%zHA|=4)u~Q`)g5?1L1Mdn34;>nkLRD2| zZ|C9CbMjre9#xoMuPsP0w(3(hmWV+9qpOWUr6tpv( zMRM@TyWaA-WY}LYq4EYEh0sJmp^mbN*v=c{4_?&!^NWpyHUqQq~Y`GyO zH*k-4%uHj|RkuSH>(T|*@mdANlX3svWE&=T7%MiaZP-W~YLh?yb`{wz&j+;~E=fm5 zn&6g;z*kP=-o6d%KDyC$6qwCivvaN#i=8XGAySPMJ)3{D+i&T%MX8~;-NBccYxDzo zV4wdb#R)BH=if6Vv%u&|WT{K)iEjKrQtR@UXf>8J#xUYfcqtpw02Zla#$$J!5cW+G zfF2bxIhuwaBT7hF(jo22=mHt^fy3byIS_z&gAPL!x`Rw_W|Z+n^Wa3tu15`J9IwQM z7L_uw=h6aKxHOFA1pUY*^U~2c;a9W6C>i>b%bkf0iTN_5s4<=1tRs!@F8}ep_u_Yk zjB;ilDLjo>P}+d3%mKaGiPX%V^wfd%&@J7}0neR;*Oy>Ij{w3fkwE><+|DE1wgEyc zq;ojtZ30JHYW*fo!!OE-2|vyWyeC!|#Fd+BK0rxMy`D+FJMXPNqq<+XXNFBz6b19I zJzn1q4<{st`s=2Bana#h>g1|OkLml~H;(^D3Y>jQf#_O3v4^Q6&>*X=DZD$@Qt~UhxuOOjObVzy{W@?T(TC19`WSM4 zl%npej3QuiSy*EGW()v3wXG9w1V{ylgaW@)h^Gdof^955{V2?er32NPR~bsN(UH9- zUVtENlvro^%>%bI30^79O4#2OL{Ft*Ez`dQZ=4KJf)faRG-~@es&&R6d|)UuRWsiM zq+#%Oz<=5zC;%evj29}+An04C)brIHopD07T*>tuK{rbI(N1yk*Fd8>0UZ>c=2=*J z$u@LCEoN|AKi!%g2p1Yq+t8UTC!{D=s6C}nuucZ~z@QxF`j~Ll9d`tY=Zg$JC!9@Fw{RTRDkaJUStbHMW9yRtK2~!z1Iin5}ORnT!>6YTr-EX{Wc|c5fmv~7p>0q-#A?%f0>r{cYa_y;i30Cf38l{4J ztuCPj5f)p+h)&abZ0JtnJMA^?VCA>d3aJ1w0IXLXj<>|N^s^>ltLWN#!TV%oqv*Oc z>~GW|=h~Y?_@BWd*#thZ&YV|3%DA7d+FDO*H~gX&xWI5(5P`ZgqX5GQExf}&9| zaI!y!)47QSi|QV^{@L2)GT%{M!kG03atv{4w!*@z&0&@4nMI}W+R4t=VXf#_I#MFp zIZRe`f`{xkHu1QJg#Q`qvRgmzPku2<(?d_bxMx(nja04iD9(dOUX{qtrltCOJg>~^ zH-gFpTL~Q0jUAO-uB-xT!X&vcUB;7N$2Ljp(8c6@3F);G3v6i;u1oXn@wL6Dd6HR! zp6gij!DUgs{{?7{DrymH|Ltn0{vHI%{NKoOVGAdFJ9`^@b4z1GoBz2f|8HBnincte zAlg?68pecL1+h9qIAJ%TG`c+%(L7|LRpkiEgDd4=L)+Bu1??@xi?PqGAUyxi+)u?3 zmJP9Q&)wQq<8jtCPb=5^`)q9Pj|q<@D5yoOhkdtS9ZZX{ys!w7SW2n5Q`~I_2EhDL z8_4-3-a#8(%N-VC=7r~`RmF8^JWp+cuCo#~rH~0kEnc7LVrZIRZGeeE%FnJ3PyZ0r zP#4u|xX=JE!r@5|Z`l*{9*l&)O1kj})GGm>SCotFf{=`DY*ZmNp}djcmValE-793M zc<7qD2iY9?`IDTh$=#Q|>$j22l&jTe7}2eg5Lft{tv>**Ez0SJio$CkbHz_z!6)}_MzDZU}l zeL1lalv9jE6a1T`fU}6w_;nzk@tr*okZohwCO|7Y*lY=IXrUf3mTMgN)Rvl3fJmF# zSeRFRU9cgV(u66YB@jtZs7&h%LE|TW2IpJMC@_nE2SOe%jiffSOAKka5^c6*=n>^I zz@@b=j5&zEz}n@j==0_i?7&TwWf8<3tcE=zVMI`D4PL&93d{Tl<}R?S`ge=QTga7W zM{oWy86-+7U;#dUMB^BD5oKKEZ85{r4V8iMS_>5(lpG1V1nsjNkud`3C%x zQ+$T{W=wq-!WsX6E#Lo(Gv)1pwv7I7%cg;4EgM`zVk%H7&p&e%o7jq#P)evjW?Tq{ z800%IFObpVsINPoLOm9*-{N z5nbLM^^tcEpWbN1n-@VWcb1tj;upp%!*TI~HcWz;Jc#GOEs-e)}ORQYOf3p*uDi^RIFg3Is$u5jAa#lA!M7-cJy!gJghsrk?6?B?YrQYoU| z=SoSvA%$8^^9AyG^$DgN=%wi?SrCn&#U{uf69w4EWSR~SF)J#$z;pg!dbnIGAnCq(bx@A~scibl@z zDB1@Cs!07Bgp|sRN0OeFB!POxF2qMpt3eI5r9waT3)mOsUUcBEJyF;qOlU?EZ7i!j z66*LA{+--g6!a2Zm2$>Hz3rZB{Tp@S$BSq$DKGxX%Js-b6g{;Yjt|{_ninV{4on+A zd1byg2|GOM7m7(E^b2eJ#pXfKYPix0feoJ#zKUvih2DiNwKHw!?k6u>B2$yCk&U>t z4bazcE#^`@Wkix^x>p}7wfhL!T&$zZQsXaY#@)94aQJ_NCv5kgbc0>>uhMCoZCWUe zK@X`sXpt2w%2*XW3rYfiK2xNpYl$}+)NnIt(Bs5Zd8+Y8MGE06u)mXddw&g=RUwcm~MbEP*jG97EmmHFV=>@h|Kah%a zk1Ize`7Xk(NK0{s`}VpT^E@Z7)~=xBXfQYHzjNKYS*<_!ts&Cf*;^_84#IV@Q1S== zHW~q2a8xx}M=B%iXoDgiMX(N&qSj}khMh8pWua1GjT$O78plVM09V=j+8v0lSi7JH zU7?HdSiswDGbkI`-MX#u4g#Jf*`z*GQ4=N;TIkD+!7t6b!;HAVy!dOq6@0Ip zOGI?T{1Q7mF47j^dx+*Sp?|7HiB9LKQeY+p?xemFpQX8o_fhKz_Zqy^hT7e@K;$2@ zdu>Ehzd;RD+oB@HE>^*AoMJf^M~!>I)D&wLnunmh=_E1M2>&vidqlS+pgHXU%hy=G z#mcLrv2qYZlfMjtzUY(NX^tA9USVV1aP`#un3MTH(hJkI>k_`$W%^JPqsDhVFJs-0m2*By4=iqr2dMs zCRX%Q)0Ww7o)hJv$`hMTIA7y@SHZQ))&cjDl*XNIg+lVTV|znq2?`OuX>c2J2*RDu zkLmGMFa53YAE`1%L72wfIG+n1x?EqT(K|nDx{oQ*Alr4m%UNm^^K7gEG(L*P8ks}M z2PZ(=qESxvWMQ3Qr0soRcLyIAaC%f%jL{rl7>7?CWjUiBP#N)Dts&h2zAl+dI#5l~ ztUTc~6Qr*p4?c#sf6d0aSetO?9HN?HdTUvg`S< z3-EGGsW|zyN=|Bn=_(PSdV;F$ki8lJ5}(fl48YrGzd&<0jP*d`2p6wQrMAiSKz<*d zY*XwCT@!RjI%h?Fu%`2nnxdAPl1Y%+sgIDO|oTK9dVy{3!^uvRz_On3bZS z2>=6u@Or!e#p5>*P}|G1&Mk#MXd&h_{Ca2jf8R&FR$ZOQzV&ZC>^JV{zY!7QPWG-2 z|9K%*J9kD^MfJUpR8%_M+j(02_4bPAB@Nrp$PILWD(d%yUY!jNi&Wuak_AM zpI&|a7r2jI&LALaS=mAK0o3QoOFvfcO={Wkm7Tt&)yC9jmN$N{_sn&ccjnH&*Ds16 z&%04SpA0odU|`mM3V8^PB<}NIisO?AaZ~N70Ae`lQdpQ=3XldhdC>>Cc=1L(qemP; zFo*A=gUwBK5^l4ik3%}Cjb%pKkfNB|UUHE7$*>ZcS?hCACQSnhCpn3CCs6<}g5n^FwIhL1jZTy2jnyxYw zvc%@V$~Ug%g&}^0&}_+RvlAV3k5%Ta394m6mrw~!+`&5Q7~Y@Q(wkhSw=lLT`DDx4 znM&qM(KQL){q?McXl+@$R`J>Z-AU?644vt{PuD`?mO3Vz8q_`{k}0A^hqgV&!}EYY zvmZYE$GMCraxxB;U-R?K?&Q-21`WVw!Sf;|->7p7FLLRz3S%vk4TC7>NKb~G6Fa^A zltmlyB~=s=W#NemGsX*j{Tx8Prgya9E#ggv=!zkBm&sH`Y6oH=R_>TZ~)EJVp zXf>4AMM7P2Gq@7#nEQhae@m^b$RJRGem@svK|OfO(CX&0pqdip!VrSxpU?LfY2R)| zh{Zb6RajhHrQLm`Z%FJq`c%08r-xuaZH+`*#jdDM;!Q$e>TP7OI(k>=3Ym`j4dk}U z4aRoKgcS=3WYjv~_E$|MyCNp)aY?rjT33*JIfAWKS}L5CrHPET=E5JX+$dxC;O%`1>dym^K8-a zvBQk#o%pQ>=Bmeprhm0T|Dva6eUHzM=(??|qcVt;S6`VkZwxMOMNh>o}?B zWe9X_yDmFQTaOHWM#U-6St^&v{O2B9?E<6N+h(sUo=!HAcf{ci!_5>}O0H6!8o9e| zTC_QPi#2ABR-XFVeXhc6$V>H3!|hHo$ELNFnIg|0?zGl`cM|-Hv?ej!#F{b##mSeh5yV&w+t}s(Sd4Tt4`%#$Z=|mN z*ZWqN1Glc|sBElO{~X~wybVc5>!LXn_Z+ZrH3HO4urOP4(E;6?GN$__rjrzAg^Mk4MdlUJukoMkMh#Hu9dl*UE4J6i6TpF%{jj7mvJAQK+J=rlEFmB4U9KCXG~f_P94k*m-NInJUgbDh&Ii#pDDVQ+(LABl~A+so#F_to0BOC`m>pHkJ?u#@Xl zIw%i4vUz4}6voAL*NPYZwG4X?(8zoAz^Tgw36zbOPmY3v5cLHCf=6mYE!5VjRefyR ztvz`E%YAmKQ4S*M`@J-M|49G4_wyg0A=_vs*Z~1Fk>k-c5nJAXW=ox_OImQE0wkmj zwhvm(0kPlg_%j1w9+XV|f2cwOJXx-1?;#9gB%?XSgd_kw7?5QX_^p(>*rIE23e?dFZ!x@1qj%=Vd`ZL@Sg)9Y?cytJ6Lj!yAAX;o1yrwdi+iR zvKd}09B!;2!W~V7i*Nvah3d!}j5h}T6G5<#sV6$v;TO>P*5W6HLjnULv`5<1&b^fPZiA1I3 zWgZRBld1G_0@WR%wrG$^mB2sEPziXSUh+)x@ec^iWvmtkIswR?CN42+L3$>aC2Z5E zj1m*N=CaK3XrtoEjN+0bl=P~q(g7LE9E8i5+lQ+QlFvP|z9+AA`Wym;&a6mQQu%Vv z9Q6HjstWBA4fci!{$%mS^&p?lc1)P;RmrCc5_!%?MpV!lDG#(*7!RERRL;@4{R$f= z6;j@aQc78A$?D+J`Dwmv%$sjzbek1?d>iPGN!AsdO4b#qPBk)YN4dw=MZXIVW4})a zVlV9hg-O~K^$gx6|G5@NS79KRUBJV37n7FbiuQj{_KrcCMcuY$+E%4)+qSbRZR<_j zwry6r(zb2ewpIBitF!yw)6w6F=o8(4cI@9P=3Z;BIp!D->Emj1K6)|ZKDdu`42xU? z<35>-O8P3@xsyoZ9gARrBw#8H@s36?`HrX6CSkL5=zv9b=m$5`zFd#bFo%wct4zsU z$JZzjh8VptH0bM}MZ*LBV2S$Xl7}tY$+y{NYjGS=}qEVyxY{%A=Iyl{V*d zKZ6llkfhFOIxV=4s>ER9Gpp6dvt_`EfXhxJU=g2<>4>b8HD&z+Kx#!8)gz%Xv($u+ z2+}c=)S;!i-7gxemmZWAh_2@`K`cLZlE7-aj>9c-K6f4d#^UQ?leC2vBF=RT;eL)= ziOi&inRo%G6bSC9n#l1|Up+J5b)R-=kOjt=%J9BwEb<#($>Rp{!AClCUr#li6pSK$ z@&bt(wWNWkALWJmNal6}?l1KrB6^y0d(p&sgKU$<*?oW}>mR1s;PnefnRvQ{nnhSe z>}re=;R4fX1WVce(vn)$;vvW?(rF%>($ySppaDpXl8SccSvj)86KD`$Cu5+mR43(C zA%|(cY;iXN>_)XqQyrcR9z_J+S!$Huk^_2&URB5^01f19u^RAh@RS^Ode^1H(e2wmEzU^Qe@1#o;`v=U zN8kLurec?J3ou0}r;X=UPFCo@j-5KMF^a35z&A+cfwuh=`v>-)H>sXn^tZ6@QGwL& zb}Z@taC|8k0qp*(0ShohUq$`Oqp;Svgv7&v7Kh0gG{m#Pq%K{nq2Z=CeHt6Su>&1&K~^IeQiBWzM&N;1s+BkZ+Ms&M1pe-EvJNelQ^+gtDPZ0D)4(0$< z5dX&=6sUa)GxGNqpBy49*sC=FCfF+>%8|cITM#yDpIjF)YoCsC@^IV72iYYzpxl*> zJSx#8)d!1ui+L~Dv-~dMBisi~vE=AN5T~(6E~pxae276Ls0@lT%5zslDmZc)AI&{Y z01Syxk_BQAV%z~x^Aqb}UmUpv>Gqt_TJ{)G^G_df1o_GLj8NmHEl0IL57AmksEoi) zfp>o*_*Xw5VNV@J`Xpfa?lU5oqJT*eOwquoh}tM%R)idB590wI7~zjQ1<+k%7$g^o z_rHiPZW1^Z_Ln%n;%HIzSdtR|*a9RQVnw70WHVvaEHrmaw8tZ=&26+>mzn_U6{(Ri z_>os9AOnoj1gwp2ywQmAzTpuEbwXg7e&(Eok!0Y{@d($N1dlY#naO;b83@(OaC7ZWTc- zx>lu-h(1Utt?ZVK;;Yca0^DC#h@fAVwjox^iZ)05ECZZf;>K12blBQ=`{z>#r>#t> z#FpieWu!)QDsx=bd*-Kz2eS_B2-mg`M@*&METxbAAadFgDDw+dJnS<3G)>M20;{u) z#NU??$JWL`XZKo=7PPs3baG59zPq%!Fjr6@4$o+t=JT>Kov_|@RMF*08GGx# zJm^PdY0=f(EP40@@f&5gN5llT#qO8#z{dvXCDao!B|3tzge|W+>!(OHKOGM2nro_A zg%d=HNE{ADiuIBmb^-|pH!fos%#>)3^bejXX_5#XhINIJ8yhfAuqLNUYaur(OO|4w zE9f9`?_iKyYl@3x2Ah_K?3M{R(IKm2OXhM1(*PMAnM;4j@#_L^CxM`T+)^Q>;Ys2D zWGbpd+)^$)%te1`L|w{;MJaKc)0{V1jRR5r7{yyJk}>lZjL=r}^d zvk)J;BTRR4IO+FvIK3z3q{}NUQc%-Fn&IS!aHkR1iAH=S&Tm}baW4^VwlaP8W*WLdgwo0m)X1D7Eb8;&Nj>9F<>Pqnu{VNkq_QibyEd_TS1Mv}} zyQUb6JNm%`nXSL_lFdLYy)-j42giF~?Oa?SS+K5Ueit0itrFN5{UH;uGNyO`_J}94 zyl8q$1Lt2~BiI+sp#hLfFI9rKHs;^mMl~T%l3I0rDdMzF78iS&htVQQ=oXNx{eG5x z^mUveqyI>lMj`zB1X%otC?N@ze~gHlGK!s9FT%nNH3i^KU36G=UeTs=r*Lu%ny8H^ z=xHqAq-MD|E8`h!@~#f^Fs!~oNuAmK-Y(^A7adNhZDds4IkCEkZtYEdUiA>>7HDt) zEV}A|2|bb?7^@|_*|gG|#gO9sWZfdC{d_A&##=3E30wbh_&qG6F{S0tn~h`shv~pM z@f0IHLr4$4y~hUw6R^)eNeVkgP=LrVo9W7*dZbml0xN^LViPjQLl&` zEfh(#zJ+g_QdvM@#3)Jn7y)Zv+O&_Z_!{SB{vc<`MnkU49;{0X2R5v9L9}r)PbkKw z(Gci@T-!riMxno-LvvsqeWm(glZK%HvO_fH&SFpLV!3;NQ z663jei<4#&XF%nuAV{4-Y@Y0$8h$Kik0lyybh-PvgP;D!*(^(N9GAk+qqby7t?IWw z3AkazKsZGg-ePYJ>(`cpxtHVIRgtS##T-z%kd&P*YZA}d&;oyL(h`At%Bm|zavgFH z#jY$N9`QVW@`o~RM z5%QQ|(!+n^dG$Jv9Y`xsL5oXv4oQd^H3H_T>b*2zDL+;;Qe+n~GQ^MNxpZJz74_RF zUKcI5FSfcEP(BEge(Hd}>!-Cwq^<8q*vw*J32BS3jYBY6kvX-TlPQ&3W`mfni^nJw z?iIEo%p^h<67jcs-e)T>a z?#TSe@|e*pTH5J6Asw+kH)NvN=x|-mDCdowXB%nw4+X<_0W`kPt?@eMK!R$}9+Zox zkU>yJ`LCU;38mkc?BsTr+;%+RBP)%QS8$&S&peS%&}s9Uaxx7;U#Yc)|JJSR2oW)I z6g*I}Y1kP&&}^St&J6u*Ow`u;u?mtI#C}u`Dz*@|HZZIWZ_E$66{gdinYb6`Z^sH; zkr$>Ub<<1LM!~PmGA>g1LPD>paF6AcLL7~I!l@N=MR22`oPpM%(T1TA6J#e0F`F)| zA;+@z23-fmp;o{qJ}+(<6$a7EI??*dm<|JqrA3K9kC_dV1Z8cRu3t59r95cn(j^Sc zW;DXs-|JEYK=HJIjzKO&CCg3?9t3goRv<-+AwGF=^_9Fg!~~3Am`#Utxd+~u;#;20 zye|ooUz^&PE{%`F{Cu6|;-am}W+86BL_)m&Ac=N*zJ+@MFhqUXqYA#x1}%9GRj*7X zn2PV0XC!N1{~Nd{Z%O-p^E>)}^ZN$=|LU&#o=;M+H~p_63rGp{^xwNK5GAQ zc1#0eecaD{Gmvf670MJ+N912M_`~&;BG*?dTxfn@$rTudTZ@8yG)`KNRdb=Gb0otxJgp2szJ2SPDRu-W%mYoz@%$? z&}>2~FZ+2NEpa7ygCq*JAS*v>$`p+HbKH?K!RwKxVD<$z{}1bg4@&JlLJ{TXHO-d!S#06XQM zOMyi0+%xRiGB(O1D9pxh3u+DZ{yv#3zI1VfijKp$*RaBHO6&@2GO@J3VERlcXNn3& z%Sur5(6K~+m~t_klJlrFzMvC*;tY9sm5NFBtj#$22({Dgvf*TEhFo0S(Zl$b=4hk} z!LTM}{;TT6_|uss51B0Ugv_ht=Ut*WWn=SCUXe+)Wdq~!cGIk~N|eQvHYS!F_VV(r zF`y+&b9oZoGZlQd{V09h^hSoO%a`dFa12Fay_6L818;HNr6*f?MAo;~GrzAhw7>8x zWrp&7Bs`wd89cHGNBP2A3JN{bH&R!7m2*B@D6e!TO`Uy75m5l{Am0r*Vw}NNwD_}L z*>USr-wdH7>D3RfR&Yg^P}F)NA~k5Nasowl7-Kbg78Xmjf$L>aA;=SQOu)ySR4C~% z4`C59x`r3E*aoc~|CW(k^;MiQ^BDHrXapC3{3Q8BrOGmsUZ;vd{}1lU+EdK2YNH_04Iv6eN7>&sWN{jUa((rS(GlxIRxY8qii^ohW!l#>=Lqx+O7(prcsym61f`k>)gzS6MmN?fi+IU zE~8tDT%BU#Hm|BmL72yY?ky2q*=1`n+nyG7w$Vu&(_l-lJf!#1iNDk-quI@Jrsd0e zl^btb0qSiPEjs|Up}ZBh&W7thJlF^5Hu1dupYHh&UGxb(tU;mrr*Qa(o!Ls zBe$TTnb^iNEshzQ;w7b`27A6>z9*H zui89q6@T5dBGLE2A$j6;_0puv<$pWr@D0Q$VBEr;J!+#$xwb4r`&St37LCeY$gW6^Ad2c>BwSfHuFn+n$x4CuVJh zI3w+;j>Zh>&hw8Ej~!JVYYCk+nuV`ri&VSkEGMCxP4jE3bbY|AYU!nYcn408IqiIl z0E@Xl18v{e31*$_|tBCGO-_im@r=v4z|qqJUu?&A87tcwq>_>rrCvp;YMb*U^ev3KrIG7 z;}NXCl6j;a?>ohBFxqqOpK6U5*~#Ost7d>&1ZiAo8))=gD8-uig&X}aV^trBy7IEZ z*rQt!#rI4dF0;i;=0sb*bFe|Q(~##4&J1B+@Lvtpn(y1vONWo> zE>W0Ru2@vj*iq2Y&mDd}FD>@mQIlmEi#UAKRLQAr-D_SlGxd$8TfRpPwA5?5A=PGZ zq^j|`wrQ5vZD)2IeuO*lQODyj0?d1L!J@5ZBBDh>sphzuE%!g*Weq(u*v`*ER^_%m zNI1c?mV;sXLd_dQt?5OK$t|;w@&0w@TC?hci>Dz(Zoj)reOUVyI2xPk*##jM$u*CQ z)cZpQk@utRk5%*=tFk_SXQD|2tSex5hRvd<{j zo!ab`mL7zwU_9c$@N1njr9+OJP5&|sY8jzQ)a=bOyujlPmdTjp){|!eKH_*wXp{w z>#Y~N(VEQgp(jM|n7gKyHI9;&B^7=XI?@Jgq36>}S*p(+W**W*XSnBy-i7o>^^TPN zA6pKA>TA*+fykN`M*Ahc<@3smCoUkK&*>b-GbeD>71E=D5jUepZcxeiP)lg={*sA% z-GM|a2y@V|T5~{leq6ggcz1hi8KFHL%!M`dA1i^N@O^DrLEi7P$})F``fh2`9rlEN?SG>#kjFxf|usVhcxP5Zmzv_@}HUZ^OkwOXcG z<_<9=w>4wj?1QygLDy_x&C+`38~O;aF_hX+RmDH;E*LMd9*X>^D^H)C)`lp{8-Uin zY^{^MZk1CvP%CTg$IIspZ-Kg1nOb^oJ-5^8>hHX9RlT%8YgOvg=v6zn=zbbzYE>}S z*`A}C>mPrp=qQk}xqa9O$a+d!d2!g&Pj6k;z0D7puLyVD(e54maNv2osMc=CWI18g zp*PLboRF{2s^6Ni)Sq4JjQ!=F@mRFfCv&kUD0v2r<4$CD6n8*Y?P5aec+<2cBP;_lIJUnYefKo*p1t6Ti6lYaw?iB~h+Lz@U?`Qg~(a0Yk@Gqfz< z%@$y^=q)Hg<+B2zXRhbcMH974!tW2t7A-WH3HORNv&pnOnYzQJ4ZFEC_}^3TGwcOx zTEE46fp7ng(Erfk|4;p%T-3<~Gk4o?I_Alas&W1VvaxE%j& zcpqwVxtE}hLPo>@BSBO^@kx@wZ$anmbaO+yGtjbB6@LSND~fXGjQ)&3UP$MA$@9K# zKb@JHHCPn_xiVZ7L7F`=+HYrJvgvB7w<{VjM2`Q?h6^fKib=TzpkB_s;1Yn}upEVt zzFnm(L{EbfIWz60Tw79z?V7%rQ9px4SAoJ!gv5=mgQ(<})|>YLpUQ1vfCi(@ zRC`9a$sxz!`#<%ux;vervK`?kj=>x7bKHMUm=*~(%U#negD}-_pN05mpNZcry<&Uw zOosC*6#W3Xzo-&Y7#8RBD~$bC_LO5wJBkUPX&8c(ozk&=Ay<&7x@c~pq$H^TJglE! zX!emKbwfI(BIZ+Y>WeIdxs>UZzEXcb;`s9exL^zT7^Gp@H07>T&h1SUL;d6ra0 zBzM{&|5Np`(sZkO`L2bC@4Dds|6UU^{|l1vp9K*czby;Sf)c7^wcTvp{CtWkjxn?s z%f+w*GcZs%d<{Ru8$wT_lYA9adlLF>?22q;C|tmEW=TfxVWWDyfBlQJ2M0|PMk5K9 zSqhXcsAqw}&&&OhYL#kJSl_@*q6h(1GOsv1lH4~8#mrz;YgUYsoA#RX?zM3gR!xJP z-^;k}@nPE()z0d5$PTWh#pNgRoe<>gQmb90R`n^*(~wS(Z%ps-NjI?A@Hf#XVLAH4 zntOb8p3R{3B(tl}^3W`UPwH!>0wv-H;lGdb{qjNy4DL?@O)!|Jxm-PJ-?={} zD!bqI9F(t?Zl@>yl9r%e%w}V6j3_2ahJ8@9WJ(3_v^%S`Z!||7-`2MEfPV?B_+c>9 zm&aZ_>x_OS>ZDi^awi+#`?L>RV`G_+pfA)N_N0Wo(N1u*w|b|2D>Pw+$C+{eFj?4n zu*QZ%vK7>dc?PR}aZSxPRXq|eThbCeT!8`!-7I8b`m=SKk!UO-Tio_RQ=H*JE47~8 z8bJr0?=#Z+MHwJo**FW`h2z-p6qDq*X0_^$ofB)S#60CEPC}9W<&*pWj3SOaSpBxm{hoy zlgaYWd_Rs2_)r{3O3P|Nh%!mZ>A0n^-@|zbCSY_?%h=#mc?CO^JTWWUWE!>U#T88Y z(wp%U>rQF5_(X(^z`I{BEU|_0AkK_fzU*~FcSpOpgLgKfqpmf>bDk;`;O$fx&wKnP z)tvJwYb1_P;;0k|bL%^8&3Q zi4CUtbB+h<1bXObDnk*Ib8x5rD(9e&cLY9@+r7E3PzM8=0WRGU_mnX-)4!~_wIG?C z(L4|J8)~{mW9prXS4j2SeF`0oIkV?siS&@8;+_cM>R)7Vw|;DjW-nzp(LzIUns#Ox zn@u;S8+xj&Y51?IZ0AW;JUdGNS#=byKh)(>KtM#k+n)6QpFiXOCFAC5!uzBwrwUoH zvhC((#-l)iAwgg#2urg*H2eZ1MF~bA2bJ-GXl9n79PcxwoB|JuC&kp+ZQ3ZSUU6?i z*4WAluxsvgb#3k3b~CuPtGu+cj&8Qrxiqr{S$WbCnR%cnT{tfSL4ca)!0{lc;pPuhb__Lq+WzXJPiM}F+chI5&_x(`2(Q}}$mH@UxpP#I?a|20PSYdZ z!b!JN2s9qn!Gy-NSLxF8&<-h6bId*<7-&(srx4ws5Zx5mBGGSGy*GQfcM7g$Zc7Hd z)i|&cC{S<_*(rr8pOYu!#0(EamReG0B2XdjOdoCI%Z4%ZkX=@< zhh`xon>QPLN)g`0-xmQzpF>fvf5KIyDgC~PT1oq>N{V*5nR9cENcF^7#78I>8m=tg z^P$j>)RkSO`-fvUZSd$Ywfu%21mbn|uy zCrUOnfpUDDUMs3fgjX~OSG+RQsbbPDEd(tpOuy1>E6VVHm`gFzK_v`oA{1)-EdO$lB#wzgc#`3z==jyv$lC9sXi(g$DF-n< z9`eAL+}S?5S2y0hW#P~}j=E#<;3w&r#WJ%=iR>`7*ESyP697=G59TZ*`-QKmo0(9x zsK}gneD^a8Im;&^JR?mWGMSR-gaj1=y>{Oku?Ojm@(hmBV3vpl81cVk{hdIS5LHCl?iz`tS)TC29yVc|Yh0u& zjoRqmeHc94?w4xF@-D z$jY})m~|^RY6vtpb7f}gRu~FhvL+>SdECq2b>U3|WSc zB`VK|G+Aieokb1HYHS0>bdXSo9gH9?M7WeJ&3?WpV7D-6j(HgO7rT;N!Y${ygcod^ zZ7XFIOTjVUvnh*YoerYMItE|1jM8Gncs|;bZ&u>+BD~l+*DKq>-%XENkmp8e-roLv zw%11lgY7{BVeNFrb4ve2PMO57tg5d803wp0FTXD8xaS>s_q&&9&K4 zi*&PC`K`+$a_?WN$`9?f^la{lI(W`dEtzve4y|OH>ah;|LL~ItQQ^5<}#NCS{*r zlHMnvN^Vrs_R?z^<)yDPm2azQ=AS3vY0h>Nr#L`S7}pZqeedGRz$^kJvk5;YtkQ1N zJca*ds3i+cX}Lm@ZZXqqgqvefH{2jB!oe&clC6d`U;XwwaF{`95QMUal+E?Sr&+WR zZ?DlNxR3jp@8%lG(y|0np?q&6$HcD|R|HmOB};`ST}!O5QragYMG+q2;PERyV9cJ{A>n44gpqLD+`*FtVT~}BIB_C_6<(=H%w@%d+`9UXlTrW=~V>#~+L)*~VMEn^}>=@GXDNPGm4L=tHcB^?)Tbp_I zpozx1xSxFz*uS)YV(HOG`;$}^t{{_vYvrCU+A4&ymJauhBN1yJwIeWM?(CR0le zL)zUDee><9@r8@Bc>+{T;~%U4q+iYly>5Ks;V)>r(qT5m9rJb7?>xjiI-`H&-Q>I0 zFY*mhMV&UA-_oCj$#mTTV9s>KA7AGp-9G(QENd<7Uc8&Jyj9h&Z8j=3x}Qet`OcGr z+r64vMa=>?dIO9$x`oW}N(h#&ys5CKpFe(}VLfK_$f(%{s<7v?STY%Qgy#%e==-K& zxy2>zc3OsDK`Sn-d&JHqNxnC#ZfkLg%1HsViUv29&*-h0Cva7@f+tV;B{)c-8x4v! zPg^j4Wmh$oZb-(@I!9gHtyi)8oX}MK_zSYQ168C9yPtzEqSg^oM=IrjnD04oO6{^E z%VW#ps77;efxvRQdoEgy(pw$4>*ID`tMcJ(7q%D+?gzu+AuqkcfOrRu@0B;qEPAT* z)!)-x2zv89pB@j{^cAuv(&#O;go)t=p3bi7W^(nu4xtU(;_9BDiLNqe+$v|vra9xeZa zdxu7LCzb-uONFz5>oOz_L~VLk2LL_NtsuP-%{xhpX#Xg)0d_-sJG@g(MFWFB^I|ti zpPTA->t-KarKD_aQXj-A2fEi#G}Eafv@MuA>li8g%RgJ?a{HOS*&WPwCz_yWY2Uf< zo3MG=O)s~7GF7CXS7O(C`iIIT5Z%T0_qm5Yq>C?h#yYsmbqSQ}I^vQTAPPk59cBLW z&J07J;5Rx(S^61Bx2TL49{%XF-Swz$q_5Oy^0REAg{Bj*(?(`seivbOqh z{Zb0>a+kTv{+?6s)5Nb1|AeLoAFmfK-$kh94nfEV7eiFE?SdXUulje;9(qo8i0^dZ zV4Hh1pN#Li2@;1c0#k|HiBRr{KW$F1e!sVDAO3Rbc92N1EBwOfG?mk;$%2Jd{pIT(SCQr%UU1RvzS#bnO?Im1b>E zU~1bZkCz~uRnEv}U*|KqYqN}fK+=t5=WI~gMR^swpBHZK0*hI3cm7mBmA9?S z>s{t8bY5Xk@)D5;tH$aN%YEd%E@Wc|PZ-QMBVM9cC)5WMK7P{g6H5t1`knHV0*Mvc zxhJ9|Z_D4(R#xkvPEU z`eq0s#}kw`4$usmhmt&QaIgmHO;V#`$||bvKj>?CY+Xv7k&R*?=eHZ%s3sc!EWarN z2zt92e&gxT{)CC|g4cYZO21RdQ~wi{JA+;l6%wxnqCRztTAZo5EyTA6`VCmmr*q9K zdBT6jY|h<7pSdc|&%SCueR!Y!_>gpJ+YL% z|M#ftQDykHi|;;I^S3#d?tkb?D4RLhJAKnu{~xZQSalr@JT;6jr1mM4Qb^GPg?cRN zrhPQyYHi3WEE|R_5VWC%l}TYJ?5wGfc480fX8nrihZF6$we&Z0UszJPbVefGN+#d? z7tNPUoCR_ONX?v_Nx|Kn_xHc+M?3z#pP+l>J+XV(Gm+d(d&e+fZN$bY{yoa!8i@yu zO#$^VRxC5&kubb>+7QWOOGa?Dt46r?cl(6_nJ|p|th+s=2MVC}ksdljd>>i##%Tsw z=!wVH5<^`Pkb-(g!L-IQeQKaQVRs1?jewG~UB ztCH}p^2}l4=28j-OROd`a`V+=90^JGr3r4?Ag=Z!;3%+NxG{!HAm98qU5 zn|o0oJF-Af5d48n8p2a(omQxY01*25Z;Yu_r6%0S+fSe6LoeKQlXeY@YVov5^14`c z8+}vRdHk1X8pHOU$f-24aYw-wcS#mjulcXHa9Xh3!daQ&Cg%_SjC8fwec;Z4IZRbn zBLYLJQ!Qo-`E6B{p`|yi1x!hx2Y#}~5@a3-=Av35XVKqDx|h zPCo@UlDY}pdXwUQ@b4VYp9|onoSjq zhsFTy3PcyxzON7Qo)|3AepbjOFazd+O1F;+&2CQxHh&*CF;h(=BIbf!dagakCh50A ziOpkF^B)Uz7m6&pz-zulA^f0f}Y9IfXB;5Rs4 zUTd6KV68NpS>R69X|%4oFcfydk2A}Qa*9Yv{{t>6%}jczRb%F_#v!aC=5pIL4J(Xd z>M?*)`wgqP>q*jP@HZ8Ig;{R+*41fr5b8MlwOg^<1xx31F_X$aATG3Qzg=o&d*Izmv_d*2I_2+iHc)pzsL(|XRK5O7aup7%tOEIiNejK zRom)AeU7IgcPmCg08E7^qe0!um~B7j51a$RC4;{j!HX{_+sn=NT&Jl5O^P$--!Y~- z92m6qphUagag;yj;GYy3ayKA0&Uc?!?($KvZ&la{%a(DL=9o}!&h?<*L(Mt3MNEd) zZHX@>hX5-F+68z5NV3@7XJiOoP-ic7XfwDl;?_550RuDY(cq-*ql7SGXi6R$i~890 z3J~Tis4-ztFfVq(hQDP{jX4ahwN&esRaxG^9*fb3Y50#t8+B05;2|CS(VN+PCB#>L zajmF?Ea?pOAYM_W1=sIEUEuijDfz7Q-BIB}i`LK8Mj(Zl>?5+Xd_-hNo(0a`TIRuu z>#(x*pY_Y5hNI16xAN)w&B;Q?tKksskKjk~VHgLUGS67V4W57|nnWI_6P^mY6Mo2P zO5nSW@*$U^Ni=P{W*mj^2m7+OpmtuT_(A7U6okth0MN9k;Or8XZ40fFrQf1W-@`*X zqzWCuYEd{^BS*?$C5qFsh5#K*bGz;yNZ{gsWqjgA5Pp#~9ax;QkB!s+^4l%Snay*b zkQvzZ2s8)nIs@Dk=DHT+F#`Ou1g&$N0JZ8bs+k>uNtMDf+o+>oCI5ZPe1SK`Wc`*8 ze80C%#{Y54{68Vp-+Fs=YW2(P6<9QWqv^SbUly^#83723Y8Ov$s zVSb9kpheQwWV;;mI$astqkK>?>PAg`L#m}n%&-5%7bkk%-FTd2+gtSHe!kzX+JkU( zO_2sm@f6>4ha>Wj8>4>%sOZ@-I8xYCI8?Du+z4h9y%A&@J^B)?zJtq+3XVMr1#th0 z&m9Y-^UE>x&TfMfa$opg$&Zs!nSuoGJn^Hl>wfd6`AgD>*3vKvo^0q)M*WB-P_%<* zSENwmba8I{qwDaRd4pG8!bkaudk7wl^&929V`^s~eq^gcB45#p8DUXME@8J!tpxb* zr%l4%7jU8YlIA^7PYkVASb5Txl8UqMI@-ifCRTX*W1UL#)+|S8A1)xfS){f~RjtPf z!Mz>C7OCp>RL!>-7twiMKkEs(@V|E_NPQKAmGL%=ov($J6jUsh2rbqX9rEZiSLyp^ z#hD#_XASBj4<49$BfM6=nXGjY(u`Zc<8bxY*1Og4cD_+PN?56Au&MY zQum16Ay{1i$`DlUXM8X@5tTn_Q=txBK54&06uH>(7Qe{FJH+91#Jxxkhq>wsoO%%u z*Df(t(?_BVW2CH$tZ4wR=&()tVS7&qf$oY1G?_AU`oU%dc!9uG-yMof}=`hM> zEX|G_N3_$boL)yw%qYVePS(t|h+HcQkSe!e9@xVdrL|mjgoZ4%!(|gaMr9Q!p|_Y) zSaM;eGEq^QN*0rqOo!393CDPBId3}fjk+FAPim#PFI#G`VqgIl)(eFFjq#I~yO^pl zGwby7`HcMStLsrv4VyzE5SuS%v@5Wlq6_{XTVd^_bw|ocP&5Z3*vJdR}J#`&IbVLmuO~Mb- zJ3?fffx)R-)myADQ{3KCM*&C*A9_8KS;a^BicVcTQ2G* zZ>NUGPpLC04ZzrHk{}z}Hi$Kx;`YilM0&4@YRmQKj$I$7k{CRdm!$xLDh1_2ZUo-PFJw-@KXJai zf>;Bij^S}iXKS^G$+&_P6hZ_87I#`aK8i^0Va#~>t9OvE-EyoxzoL9)M$=vK=UA!^ ze;@IYmxsG<5r{I}%->_S_h^iwBEHC!zq|7PKCI;JDLoXSacF{L;a3d}zjr0rO^B9q z@nH**DshiL2d2f@UjpN{fHnAptM}qCN(bJ&c}cssmmb=qY$P8bLJ0d($`_-&ex#UR z?B9lRHUgn^L4K-m1502@m;o%rDuWWadMz4^yB%9=_OuL}z+8?40iQsfs^P?hJnv-| zz&$y0N()T;ASllDlHA*2`XNq{1JJnm-2$p(-pF)>%F?5|R1P&kG{awYYM9<+w7;2n z(ity7%!c@&H@??eZ>L?a>2E0E=yz1MV+fGf~q18V7EfP9r)*BEyC$|OzOg+QOYg0Y#^(n9E36PaEhiu<; zTZbt@Yu5!?EkL>FPTC=JNCTO8V1?f|lxjH2>z*RSO=7zkGe0i& zb85ERGXS=R{loTv97O=-f#Ffzg9KxztVi5O_XFp#;Sv{y0C3mDVV#;KvR=DvIlIrX zdRFjKCCk0&eBKkdbqF<*-I!-c3G#6eA6`A-h@y9p&>o9?Xu;u<7ROxyQlvP=Q-3SX zlP>#aHcb-8FK=f%Zp%mcR{AvHdBE3@bC>(5$v;y<+R6(iD|%3tMU;pA!CGWz*+wxs z|D~3AB>Fo7mDAB_* zE(5YGsN!=d&#YMR@%}pS^cfL=&`gFqRV2-tB%_J2BE&=QlO<(1dlEkXQ&unvFbQ`@ z5B}6wHcRu)>Ri?RXil3nmY>m?kQ5~h6vc3cV&=i)_}a=h`gYXrkjfmLnscV1#W)`x zF8qrg?ekD2otdH}>2DmyhWDo0G{{^jlSr(&lWR=Qu5$UWhEAPbtIJ?nf;;aOf7Ni- z{Qua+TH%x^2=8q@7%IMXGfS1mtOk!%q)D!pm$JK24H0lOKSV!=mQ57iYglEnKOv6C zDXTE%cwX@;pMc<5d=`@`#x9%t|GQX9=%n*cXBH_R_6Ddq+E;f-$cwIPOCA>w^5)7) zWha*ja_&p$t*B@fh4T5?0j#LkZyvk!aIz!+0) z=}hhu1t_%5Jrb!Hi=w#@(naTr3hCD!yCg;<>KbeCt*L%BoYr`u%kY?M@r}@5VRHJq&@#c;N!ozstPTQ((=A<5Est8Dyi1O>Ov)Z1z^PJ zK2edU#d0!+`eQWb8R}c;B_FPnpMc|8dW!gPrP-$3iBW)W&_+GC-}^&+Mo1P)0Z-g5 zyVpoo<^c@2fWp@gRByAi!DI=_y^)0uv-!d(M62=!*ZBDHo#hu8i8sd;6bME9y^Ram zc5I-Q!AJs0-e!@Y7Qqy3mWbCGkEji`AH#FQO7*8v*;{H-ViLx~(JOF=yEF$Cu!Pxu z{%t68|1tDw^20OTXmP8gklu&~OAYs!S-eFv#w)~(zZNLfmP@!T>IhF5DbenaE9Z&L z1b(g_WqBRi5p{nBn}i2X55DntqzLTRfh{L5tCOVxQzgR;X4Fe34Cgnie*0nT8AZQ?l=vb{|k zBu-}@_hXaIONU#Z!R2o@#bhTobJoq7JN((x#&hyEOE&Mnh`ylNp;3bqo7)kRKO*Ik zjAYZ>ae^v3Egd>Ed1jHKsfNcy~H|OQU8f&u%xKEYSKOv$n)b zLo^l#wh^|;26*(>SK4uybg!H?EWOo{`QG4_aiiL66Z!7&nD?r-h`&4Zs7$)F9gY!( z8yMYfs=5d=7yarD7@&Lbu#rCuqrwu90ryR&VJY2##NCBucAEz+6= zKU`z8^HELM(yPK*G?s>BR-}sk+_ZyiO8p^5kf}(5E6xrZ`-S(r1nIVBZeln);bg39Z$fgzGf@9bCw(CM; zns;f-tHz;X8m^;YPW)E zd}kk>KaNd%BKaQ{KBS;RrvOTlyMd8m=`sc7dq|D2ByS1jdrXbU)uP&2t%^$GQexn1 zsJZ3oBPwV!rlvxfVi8$$`aY#3n+4bvILsB{9I&!7yX}!=U5X9SX|5t~IFx{hZe)u# zlJVT#GyetPMefgzv015KGM)t<+2nQ-$XhY3Em9ahrg1gj#I`+V(bgKYW?HSnBh8lx zN_sYXbM6S*N{_4O6g$uZnP4vrXRV;^l5o~tG&oL}R6?4@vy7)xB8rqe6A+;4)IlYl zMy(-q&CWERuWYFYc48U4?xpMyro@6=yU-|j=hA4zXZKLOPyNURpcuLAOylA?V&MOP zjNL}e80J|n1s0j22~ZoD=3wTl{frMa;k+s$bpoM)3N}JqL#*0)6Qo_ZZGcOD5ZU4n z$F>b4gcTvRk%54Lr05|Yo)z}x5dIC1C9MMpGRl6kl5iv+{38hKM0L!A%y3UfDnOz} zWjarXOKICrV=%iGbS8m-uFcsjx1zun45?Z;s+cmMY7twR{ILJsF{=l0eqxDo8aYUs z?9dXe=tQ%#i~5!651wtB#`IrN<^{FsW0ozthr!>i@oUSDqci++hcWqK&`Fyj--WY$ z7!Okas_dude{Jp%6x{rq_Ye06vQW_%gy;nIpKUt+aTovR)J5%FES`j;_br~8B&6+H|SQ4?|u_d02cIyJ*N4Qti^Lzg!nkAOy<4WTLc`!CM@1tnZ zg+m4mxs;TJh5zmUT8`7K{e4D z$cY&Q(Hf=`pnX?&g2|1Q2TKDwL0kc|Zd0?_RDd4O^=4=(i59$~_~yk#E3Qg23XWfi zSS)pCNhC6`{aBgI*-|!uOt+}2%9ir#Gt-2Hqs&4Es?_0?9;OppOLmdJ5q(jnSsJh) z7M8SkI+))0$PgkbLT*QNZh9L=mT_^#94U5W6*LFAF0@mWFZ4~7i5hf(U6P0r=h~z4 zBsT@Nb>Fyxn(6NVMx*I;KoK^)NGZPM$7mYM={VfN)t?UQ9LLAZQ)k^&;&s@P6D92t zhS6QD4g`Z1mBpk9v796+e7N;*bIM%j+?lzuN~n=0+V8GPbFhGd1@Lji)dmeLZK~Vq z#u_wEXsVxSLVLO=k#-i{iUV8=Ez65p*c#m>m1md;!aziT6q0{V?V5a0!MUgLLTzc1 z`euuyC2n7AO_sWB(03IyQf(9z~8KfDXwsrp>E5ze-?X`Qgn?Mem@LHRg!3Z zfQ5X!-dI^9X@E!_*u-WwP3Q^UABur@Pbi{K#!_ph?=_ z`j!)~yu&^JBf3OhzD`xv8Fufl_QaeOvdSqNkqx!(qQyNqvaJ@>ttQwJm9m5oLXs~n zseJqP%#y@J6t~rymdy$Vp?uTS@&LS~KM>syaZHe(P=UAZB~0>FRIIaU)ff`bef}j{ zpyHOWKFj8;h2R)g%UZWUO8QqysAwbz5#)V-b)XLD_x9a1YQ<5O7B50&vyC4{4`r`y zKUw#~ko*Gr#_@xkO|S~){2*ajsYH0;SN$j}E!iq5>GvZshEUqH1I;xE1&h1i5N4a5 zE23}kiPu7CQ|4qbnr~pHFN#t|;l+dBI45pU*k5GLUtsJ|VxZb{e2Y+(M)C9jIDBnnM_iJh9zaKe*DkOS@cTMk8 z$to_d)Q3pvQoy|#?pXn$obfAdx1QJbn!Z$n#0YnJcqN*?X_Zy&P5#+yCfJMejDMs2 zz26ayH(%22t>UAWmchL={}cDXdCR(e*NgA(zX8_EVf{;{U*nRduUtp{AI2rBR(59p zElT-+M@O>V+ z*$c+@W8{A;ind6FK(j2Kn%?Ako^C(h?tZ&p`E~t`+LIX;^pzB#h$#dj)}0KSoD@QU zrO9fDrHPEGIwGH5lu-31G@;C_sy_jJ5J5nR6{7wY({k-<`ZE4h+&TRMH{!Bb+9&+U zjRE}wco2K;q~- z+ub2`vL)-sbOc_!%_~7ni{Dk9*{a);w?LO7O86^U;Fv$sy1`)~CTXr!5jIb*;GO;xxn>#>o|DFn6;NgYzlrUTay za_#3Q+ogY9t(91i)^0Ov3Apub6e>;rjtUNmqD_z|Vlo*S4-J}BXKD^q_6;sY$VQt4 zp}6Kelf<`cru40o*J6C08Hj*aCwyRzo+q&CC|`O?_{5%{ z8Ig=~a7ot}TnOg$ryrFu4|3rGMonD>UX0*wm=cJ&rES2OJ_Ah~9-s-G@*LrsT1EPYqnAxa`9zysL_517ET_s zKq%BzTl}HD;njjhU_^UWd62sm$7PwD(kfl?fk$W`VTuFajPxcd?09{H``7oehlGfr z#TUw(jP{>V-v4`6|M@o7g!08TL;Kr%LH=guF>kU_x;4+f5qx#D8iM~IIZq6Sikuiw zj4s?>x+cYJ#^7$Aq+I<4@_H7O6M6q@AF{4xKnm0=s!nY64ZwS=9sC}5j;J%VZz%NEK z?FfQz!$Cuh?$Hx7$@+^%*&0P0Q;VnRu4)1HMOt8?i;j#;!6QA4%Po+K;eBgHgDWH4>;rd z(hg)m^`{CjpnBKd<$#`vfa^t@y>EP%-+hMud9w>1_;)T2?9e4Rl1+`Z!Hc9g>pcMttZ{VuahM(}w#@Dq~IGN&Rr;ZpJ>)l4%)@Q#_s z?mR-ze4cRfa=R?CgI(Ayk1KipQa7~$r_^|3Yb7KX+xoPr$=tfU25dg( z==pN8pmIw#$AN73*a@`_za2?zK7KMq z_Kdxz_h%bSBxvjOJ70s&Oy*tg5ARE(q!>*W8WW}oZUqG<4`DOqLBzAzq8~bZrmM$h zF+wf^Mn=v4r3Lh3YXE$X#*k6e3GO%NQoH69J~b<-*!uj*@4`d;?103O5|!D`mo*>t zI3t9zeLLf36q++*clis*`%<1xImP}oD6COtBOay@nxY0v?k`&S`ve?7|*h z9lKT#81~oN6YK8+V~7!a5@{3~32iQ!v~Rc{Lhk?#Z~8QVjkxkAL4t(A8C#8b#8PL^ z5nz9wW~Cac1catY%DHiM_Pd_6h+fJb(;AqA!y_h0S0WI4tkq#<~)x$%>IsmGOvX0+D_x zh>j;|#Wn~Zp~uU#db=~1v2~~>teHi20_Td=7?Sry^28%6{SH)DMG8xZ#$PW-GDwlaY5L0`Jvc!h1vvk%a%}~tlH8PPE*NsU@@t4&N1qW zIpRi@G?b=JR+tf@$vA>25`!+0)o72^F&=nXheavaHHqOq#PE)MplsT5HomURpd74R zrwz*zurbPf7Eg=QMM|J-){CUZCX16^9OI8U_;$In7*H4Z^6`gOGVM7`* zE#%S(s`iMQDV*t4G+lR^53)wC-Ni4Rkie)}$8Sa0HEFb~g8ZdT%-kAYm-H1!j_hgD z4FUD_c5r#Na!CGH+kV5}T-u59UVCS2DobN>`0p9Q)S z8@0sJGK+S$}e0VC%;nN`5?$#)F~3Y&&whp z?6{`@v2 zZ+gYcI%Q;-S7UJr;yGrE+qQyg*8WNg8(KJEhg!hAhle_$uZm7Yo!0(JL88G@!mnwO zI=V0JT1qj_J;G5);XK?P%xf&4l0*Pgh4Q{h$2!TKWU{O?Ue7ON#GLPX(5Qvq%gGTR=jpVohzKk&9dQ*OK;{%1F!tO-8+WH#e8{(vo&?s z6^MP8JcR+JekY-Ydk3dR)PyD==U>&w|Kd4Qgi$92aAmFz%436z+0O@vlzT$vzTwWJ z*17ELvW?~?xfB?EpMO_B#}|aq;5M*l8wCbUnz1{3wK5&&^u7gc`$SDv;?5$6MI060 z%R-W1P7z#=*`RUyqvz&PBSW-!Porh+%pCYvQpnBcZ_!sa&I+p`oAgwvj0+1j{cc+dDBaNK#pjge^2eOq7~OgQ z9P#?W7=e^!?-aOoEq>276&=u|6T~oE6}y({ z9VpwUogf>U)9JK4I_zFE=EDA(#^%&->!wy|W*fyPn*1fa^3rZjjloqGOzOMJtj>q5 zyAaJg=C=JctC0hiLq(PYES6J^k>|>c!q8ubSI?7sk9|cx7#DS()EEjx8(9C zGN<2l!#J9T2V5~~M|5_EYFL5ZJt;7ccCTm7P7W5hyI&S+Iv|U&)}spa5^;t;0u~Qe z`<`MBw4UCF1FLh_Q0@v^-kFv9+1Z=&|YLLyg!v42?n5oRS>pO@r2 z5!HP_?i1S%;@b`ko%E5l1(0|$(VNs=4)JXw5bVTqejkXK5MP1$vVdT{He1^Y_h9mX zd*0vb+Q;38_l`F?G^0f5@lx)yfjG%Ma9-Hb6lk1N}9QIocZ5cX^K%nQif^JWY$@q2<$B}i_t+sLSY^i&HZlBV5 z|CEY)LS6HUr2AtY_KA)T^Mcj5`5|}n_g^2Yj)V4dqhE~`M1N3qWW*w=&Y%mG7cXD?#OgT((lN)$;iWD#?m8b2Tx*3 zY{VOES}vmn0tAfO=5go`KpYfhH%l-+L4Jnx3h_E<1;`5SC-#(GpSt88d(E8w`B+JV z2*?@@L+ZB#Gr^48;U)({5}}D>GtZd4q^2^GiQiWYnVFhL&G@GEg_=wv0wm={hrAzA*SIE*+mQtk;~Uy`u`J zolQf@AlXiAX*|`8(+eP}<}wlDXRAdo!v9#^R??;J3=keFJ24ZfvMS9Ikm&|aNQbIT zZ8cNBK0t%|h+qr_SW~mj9BR?)a8!|EI&#ts%pOWFMrDpnGCDR;ix@2Ytf)8UuC19> z)7a{eyHoi5%lPwt*w*@&$xUkLN_9t#HG&&|&{Zmgf)h3r^19e&{7FeVIunTzx(o6V z6UAO?2>52IW0-~Ui8*GMXa>>8Op{r7E;HZy>bxrTb?3<_ta4L=3}8>u=_mDv#Lq4X z*FP`q2$-UUlwL{KrDrbYGik)ga%*TCr~lTcryJ!Jsd;W)>Ojww z2;iUirIaiu0C;QG8P2zmBNxTR>hKG0*FW&ms`E#;ZX=W ziBJ2AZ*&jBlOKo|-k}vF{?reLSsV5lY;+Qeg^4&`u-O3F;QN!Y^^9WJJ9NPKXdRNt zBdtCnX_?J$WRgAzR(gUmEH|B~njP(w^ezacOJ?Iw|I^sH)QUNrwianx;&~u zH!BrFtE6vMRPi!8B3`r@VhMr?%JI@@U=FcO(s*30%~~WWal0^{LP4q^5ePd)h)u0% zAdvmR7Unb4*<3uGpHCn68sDBBdjrrmCyjmupxPfQ_1WQV&6O6&H3@3UNL=DRIj_#_ z1`zFo71Uv_e?)u?w+bJ6r=q;bQIiPFYmDd=br-#$6Dua-FR3`_(AVOGXqQN@{P?pC>@Fh=)2D}T*&ouD*deb+&s zQ`wdtbf;a^Vl<}gf)qXtr>Ipo_*6Lz#LtOft7c*S>l59PZ)=Q}CacNa5fv$gAypci z86l#I>Hf(_0(dMhvrw77-xcKqv!f%pPQ%8=luN$Q)ERhO>U$FQ^C8)lWFl+F`}v?s z*#q}cj4Ask-z{-UQTCWrr+CTa#32<;2)HiA0R5LgjK(B%9B<4%_5B( ziEDSLy<(Bap|rx7-RyfFk-E4gjyw|OFjpfbrJan03yaj&OMVEyrG#9?ciEd+c5pRb zW7w`i)-jARA(MOamy@EJ8cVpByz5sm8zj(;2a?b0*<0Z2&i^7?+FwHI6IFZC9L2#&g#ieRSP$Tu1=1Euf z>&n;K*Uu7uPQzGX7zD}Fgihik6a>ER?=IE9xuj%3jE2Lq?{ltwpMO8+Od0(B{KFG~ z^1>Z$&x;}sGc3Xx5CNGxGz6)f9&HGncEDV-+YafZvtC!+qpBdCurY8Nkcrf%a|&Xnk4cMAo2$SD2fh zOZ5TN-!PjCMZa-n5vk9J^3{m%zR(-lEb_Gp4RZKWxI>G<&iq(IxqIBF0sOsOpQCf6N+DEr{ zq1}h)s!l>3vAL`CBT1YiTVNZEDRg8G+IQRB^#paW_Ke!M>k>iC!@R&cn6gA+L*mz(?61GF!@&a+Gk#?d4lRai7g%*Im6iPda}sU-eR!@46A2 z%XLcT+tgC7ngh!3m-bcQ)SP+zw{|N5mTULmd;x*Jb3ZxN)%^`KMg5c!&FNqBJ*?MI zHH30)Ewa)Az5NW(^fS8bRASY)Zx@55@|`3$v7Pi>v~scjSc{h`Ck`%KcwV!sL#eMp znI`A*dXlC9g_Ms(bOK{v`;?CD&$#&l(d20sv; zm0s(E0vlKQZ^F6pgwt?$!;UerBT8>e*@UvcuVY=teDnr`w8NPMU&sMc4ft1Dsd3jA zYIjkOT9Xy*OpY@Qb@n&PTTQhyTm_>LcRU3FupJ(7NJDmx4?wCbAvW85|A{@x7N#BB zyxbf+NsZV>Of&u^<8s3>KKII;8$zI9qYYXP*@f8)K2s%jPKWgB$~P&nV>B(`=QsM_ zVgutJy&OU3#Hs-~2R$kI7x{}%v%T5ylM7S9h6=M&l+!dhOfC9-Ce%#cLMI5*r=_z$ z|1~K}lRDTgee@%*>cD4*s;#Rh1ibl>Z|3|AVMxoyt_(e`Hnk%nqwdfT@ z=BM;%B1}EG*Cz;aKVD+x)v^ zPrCn4FQE4kY2fbiP9sUMyny-+(#^Ar&GSCp0eD;iK!5hKE^+~ek^Jj7pj_( z$P(ET$@hM7efdx%r=JyWXJYQgm9*Kjn%LO)&I56C0jq3j2utp;=zctgGu4G8gl(4dCm)-m1<$h(3C#p zd8>-4y*PU8W#8wHWqi5mB|!3?Q6Kv7?&f)!j~9egL|}u0W94)3LMMEn^e%h?{nwx~ zm_?}yzk>b8VIcnBLCYGs*_&AY7jOFi41V0A<-TG@3^i!Rt^w~v$Dr56@rF=BM8(J@ z94-(TM9oy?&4NMLDHx=(-{g$T*zNcEeg5GIG8!)_8KFtYzhq}(siTc7`P|`F%GqL; zuU6uqZP?*7yximZ8Yrw}KuQjB-!Y~}NT6GLrBUT?Jt6xIWNeztdRg5^A-5k-R%_~Y zznvHb%=|CbX%G~jZ`lk;CnV@662Nz)i^)Rtcz*8RM)}C1yh+JlU6={%|LVm4an%23 zg#WdTA#3I0`d`JBhOcP=JHEM$TSgJ zT}#E~&Gvb-$@kd(@5}SA-`_Puqmb7JG{bXB%KPaXcu7;Yj87qr6flV{QtB0M-oRZ1 zf&Gk?b5y&#jQIUU$oMET^iXkWLP8!`$|p!s*ur%o&5BPEVkl=K$nY|wlB3eIBBP-< zUwo+-DmQbiNRrN=H*WaVyh84aJUvZcME zBv~r7+{232Xw!7u^w_>cpIi8?(oaKbwAu666ma13Po{8 zxKMzPe~$d3*VR0_X(K*HO`_6aqf1zPL3Z4Uti@?1K5MdI94V7Bp{u~pW31{fUWxTk zDSjQ=y?K+}&_#A_P*R@ zl(foV<4wK)P_ARUkDN9n8*;=Y?j4iPtb7R#KG7d7K?q0VF(E5fnW1#ijSp3_5 zg|x)nfO+b-UCH+eb9DYrME2ZH$FSXWDz{GZdgjh=r!=D3xSCNWYvS$&K8ewoxL8s3 zn#0Nsv?vpL<@;TcXo9QH_nW7P@%mMa>A7+dW5+oG`@T(W zY)xPuK|5cD1mFtep4er=p5nt+yfph<*}IMuPpN!9ehE(KBWBqHP*^kjym65lO7dI> z39=>P=KLqhL|uK1>9-H};5<1sI-Hl`>-$(5vhg8~f!~C$lattoF3@@r%Q{=s+w&h+ zBHYk>rJ?JpnPpnKQ=M#cjDH=GvLRuiiZ?P^^80D8`L?e6c^M4=IkkD5|htd(hAo&{W{HmL+`m{FfcE*A@* zp01@%tp#r|e~G?eZ>O+0cTE^$w$Z<+aeJIiBONKMsDIK{>luUpl45z$Zby0dK7d z{Vv@_dEDd#!A|cG=usRVBf~X!yayhpOE=*)w_{Z8HLgo{UrcxQN|n76II27p>pYgE zYwAbt05SKBLl}&v6h=d=z9>s~h`cuzl{dJSHyV65;Csj5%I7(!oWmZn-msZB4#x@J zX0gXDN_UvSiQl_8!45)4kiaR)yBL8Ao1ZY-1J%$8i?&$a0`{LE>{FR_S%da?6UMt| zH?XXR(5&APUaRBZpbdFM>cF3!_8l7Cv#PrL*Dq_I#=}#sHGO(#mDy|v5Vh}OuFOWG z12QVqc}D{hEkWIH;0gXF+Vic~&*Q-h%#;U$A@mFTX9hCT`Wv@CF#Kx?6TbaJ)%V4j zoc*#b;rP!b?7tGcnTwFU=|6oo|3{)P(XesESwj1)rL$U@PvitLg=-`&7T>89^CH_) z3^Ku|kGcn;P=thOZP@rEE!D2-WncoUX00Zw5R@quPe|atuQR(sAj7ic$on%-J}6kc z^xvfAP2T)4Pq#Yps52FFKG*?Tx_-&E=DJ*Q{pNbsJsoJe{)^H_-c_=1h^w(b{e>0N zb8Xh_=5iKdt~hn-{-(hwjg8>UWU4TshKE_;W}omP57b(P!UgVv;T|09Sl=L93hNK} zIX|(1IblPiw4s9Ixo}^l9T?$B6vudR@gj}{b7GH(cyb0x+>`_IEIoDei8%OA(}fJd zL8_XL-vyRpt(j6ts0reyms0i$+8j= zuh@&_!I!EWS(7=9v#e$Cg)6!orR4gP_c(B`s}(yReJJ%2WmH%@+IfFG=s+x$nJjKy zJ(nVIPTSx2y0h*Fxr(`fAYtcx3z3x`d_{N_G9pY@kN_3bZ)j+F%2~~VgqGm=MmibI z2{118jj+u5mJjV=M_*O0_JvfBhK52RS1G5~Pu!3$G<= zQL0B5(B3{ch}=OHTMU;}fn9LbpV%{_^uw|?p38j=yxW_mt4;loVzGF^dAXHL1<_XGvy2?BD1Y(3}a*^b?%TdSaO2cn5X0u z@om2#HV+fBn&8J|2CycOOALQRYU~nN8#_2FGx8(S$2ZN~mR5edl~v zT$$e}1wX`jD2=%;LU~T^cFh9J1F9DXN z6KbL~C~MSfbep0QYL9<`<{Y>scw;g72gt0iCl#`wA(bhuEZ@?fZ7hrb7CRu2CK_Op z0!7S`45w#}gv}gcYXiL7iMf5Y_P{GHKDGspNL#bum8&eGD?dhdBy=K)xh>>SdP{Po z6|*l)iM{HNW9a>sezj|hU_Y&Y$$aO0wGa?|h+PPWb0ckO^~lc?9{7wk%{D#YBR#0( zvvSP_id~MWmDOjy{{iQY1+PZJywVj^u0QV)+cOUQSx~{F%)E*xCzhm5-5Ai~T%`4- z88;zwa5ujo={6!t?GD0Hu?j+ua?$Vci-JKxY)MPwhIXu1IbTP{s>FnwtYq5iY8hk3 zN|NmcxBKKwtpcF((m&?#StDCrBos@LK&f>!9S$AB12N*_m9b+06FxONgr4h2vK)n9 zJf!X#kyS5YJ0djqL*ik-ybVhs>N_sVuN^X`aBwG_>2SRlNz+>brjWQHNPe`=+YHR1 zV`G9IM3Wcki;}`kgpp|`KUgaEIq$dQvI=$yV~qkjm2gAja@s;u z8p0S>YT9D3HX}Wfv#W!e4z0PO^hTMRxO)Z>-Ok4!6`PrKTbYD$-0r^UKwmBrO4Hqi zA8evS8`nl3ik-mj>`k~Fvsn@<^&tR;k?W}JXFdFzg8#kL$c7o}m-85+$Na3`>>y{= zyS^^uXJ@t-I05CV>o*av}{v1`r!qg*fNZw=q!XETs{qT#JPLhj$RJYUB-Ub z$Ik(USA8wn9JAgq_ychf(kOo&;D@n2O9%!~5;*hn4uF`$$2yQ)&IgB%!IU9$(T9lg<1S?3Dn=oP z{u+=5h&NG0zEmL$FppP|SN+{cn_+JxFVH>IBP&5K-e7v3gyBC#JSF?WL_9@T3DBy3 zBeKLnxpIepRX^freP5L;h4EWeM1?RXwp^q@i-8yP+@$k+XJ4N1>+l(dkee+={lVuT zPpa^1o7F~F+T&G<$z~oq+6?T%B#LM=k_@Isn6cz@&9zV_xP%gu*Pz2pGV~l`fXFOc zP8XmxQMA8>d5nrg;wd$`C7x|FNaV<-s^X2k>UZ>-KB$6gmJaGtxD9&lqD$9bOS_}Q4Puka^aWGQi* ze1d%{h*3CiE^la;~|cG{_y+Ic<63DI$5z*%SlMlk1u$l>Ck{uB?G&~u^UI04U4_fhuZ8jO^TWOwz2<~V<0pv=lr2K)?lBbu@~Vn)k&zUZ2#9w4#0EYMptC!jm2iw zzv9VQ&RC*^FU!~&a9`?EltX{{V&^6?U}YKbhek0hb^=F2oLOU(!CJDb z4zSKfyZlSF1x!bd?kIVzWgh9gE}q1?I#Ta8gw}z;WksVwg!LpPRb?a5L|>l9M}n zH(V(z-c~L*wDb(I5q>HIwCL^M6Ap7m{xol|`4vO46^6ych&(u0?RJBq(|dpHVu0 z6@McbfC~s3J`E_%$ANl9Wfii>M0E||6yO)qd~PE@(N8))kt=pWN)Uc-#@fq@5NHZK zT5|)VK$%lSqQil_N6)|xKbxZyYsSY4ZyhoSGw2g-_R9~4*9W~elE=qDTxxr7wNA(H z3XqQ>I8Op=wbGT)EAm%Zv&`o~v^#$?=ra?32{<7x)nVi_lO^`{@(4J4r8RzA`&l=P zBIX;Ns0TAr#F-@ciE=-7s)xtx})5>R8> zRmvHVn0axb43K(Esmy0mB*o!ge2h?4phUTdbVyk_N3Sz&lPc!I&tMefzj0 z5A@~PjMY+j&0!^X*26i;krS=c9ht6p`39$}Ci+{j=E(zbx3eJW&7k=?m2|>xDYOVS z&?dE)2kNyv%K>j@zEi&_+IHt`ZIIht4xtf-Usbd^{L{sfFRG^K>*wmJmk%40miSY8 zhqhI=H!$#ouuh~Z*`eR;q#zbQwNhd&+5{15W<;+T^yk4V#h(|8yU!HepF}ePqmLZ0 zyVth+KT{8j zs!yz0t1Cwx9uaD2*`&YB--H@@4PXpIIlKU0va$ICnKcXH2pXm9V$RhLG9!~IGRAxj!EOGxLeanDkz$@-Smf7m@_*Fjm?WEj(Cz`htzb6j zCu$%;s8NNiCd|Zc6D{8fiJ4NZ+r(}a>3zk4RG9;Xrc1bNF0(T z&@2{85^Sl;Ij=HF#IiXcRIDXJU@z}|h*g1g^dojy)nz?1huP;LL}jPORPky$w~DW7 zJ~J+ti72lrczV3<)>IWTOJ|i;x~Byab5HDPu&=%aSR`I_@sSg={_UFD>WPq#n^lKM)4n-+{|!IJ8py1?0`Vpnc`y8@KfP~7(y*A$cLd`-n#>fM$7#%&=Ja6xg&S2;Yw=MoPD z1DbiGr3eXHwEp78caTR1Lb!O@j&G7=H<2%O5jTLvF0yT(EeeTh`!ko&WOCO}9Y1&x zZ9kBK%w!Vz>Ts(K?}XQXvqD)MGx;3(I@CH}9DTa~{N()K=u3{8mJ04a^a`6?Sr&{k z>NzEm6=eZN8KQF00hU1#LO;TVM~zXl3Id1qhp+HMEOYNN(|C`DsH>Wl4};aHLen)% zyb`G={+hHWdtc=Q*0Z7>6}z4=H*n+Ok)p(O=%We=k1qD`=YUstu!hwvj#ghBHw z=cB-{s;X9RhSGn4tqtxj#bAoLr{of)gze8w-R%&1y?{ zT-tB@SaRAwh16x&RlsGQ{dNQ5*QrD$S5;DZ(m2rJq67y*UII?j`w5Mxn^gQcrk~O| zoFpEM!`B^;Nr|`*rX6)#ycU?mWuBUMQJgT0cfiepAIU-!va z3~SjhH~}1_ji_uFlbzeT^o;KTespW<^mS?3z%JCQ)oQ9rm4{7m_%_{~Gr1IL`+hQ| zMZQvyfqSuf9Tk$rlh}QTj!_@u_R;mTq#$-Xxsab4iCpbVvXK6};oE-Rio!kz6~I;S zY415sky;c?dB;{(9vjbS33C?0TqRdNrIF2)1YfNd+Es=J8Z`kFuwv%?T0T|hV zG`!C5)62Q|S?HFHqA6=amaD}All+f;k6OCyjFRX|cDP&+q33gD}6v z3iXd*)2_b%QndGWaz$;!j(iD0OtSsdqeuDsv_k{Qnp|JLt3vz5Ui@zAv_PdD?Hk?21LLp1;E;1l+n-bW9F!n96|xpCi@ zq@1u`mb07TIL8RDjP^`@4AbNtn`I!!=*vLKA3KJLKGj#e$7V&bbtYJ{h)GoY1_xOC z{b|=_%M9wJLt|>(_GZwGd%%LcC24|c=KQm~0aa3DMRb2$M1;Iqu;tI>Bv&UUZC(>> z*7c8N>JBmCi7QDY?dKpQyLawiH=TGws*~s*GerDqyNr2WJL$2JPD#8sj&3)fAS%C! z;X|L7Z8bc&Gh^pK6psn(L}FhIwid9_BaS$@TA@Yx!=ba{u*3dI^ddI zg*M`u&Vox;W_=_Ud#6_>sxtgUk~(zEHbG7f=O?eg-~w{$C+036A~=lpPTn0>%QL${ z*VVgC2iiA=+;l&Y7;6v^^3UfeH~ucNMmsyaQe{h;BZx;Vt5t3ELDSYa>!Y@&o-g84 zD2|92U8x^>LTm|P_={Y~wpsu|N)LmAnu?6@T3;dQVReNa0J&3iU?ZeGJv>bB5%w$k_^lrO9i=||C ztbw*mUL2X?CYI}w|37c0mrg7w!@gTR>G%1O;Qv|?|9NW+QL&L(>M@S~+pN1kC{BrTk z&b{NzRb1{)52(35B?4F@Rzq91xf7KPoC}M}WM$g`5csF&&l~f#){tGHA&`N178?1% zOdI-Rsy|H8CH~}sPT3>x2FgWd&*AwSPPzGYn`jQJciVTS=ia>xZH^+zy1P>7!prL# z+S(p{3L}j0akDMo$(cFryV?6#u(<^kscQ=7;AIb;4Q-S(z?4tahS>HvGuZs zoYqL+f_jjzuC4W>IY9SClG!RW?#50FF@3#qDblr9V7@ogwc-RjZ6_|rdjrpS#^WHG zN$~?NscddJmWn^orLbW}nHI!TzKv&o`}wQ)+$oy{fbLr6*22p!P8@cr!hy+VFoOL! zfkCfEJJUhr;EaG$tr0g2MzMV50yb&O;V-tb?bz)?y+Q&DstvQXIJ~@+0Y%QKEnT_N zh^WpyBe?Jg1s!wpG+tO_7#ChZB8o{+k8E1Z7U-WrmXXE-Dmd`M5r^jzMwaP;uf_ma zW?sXNgl65#Eo^D@B~b70l~^}jD4{&}jkaA83^4=+w-(QdZVIJmo2KWK4+SZ^SVrO| z`WTIcQJYX)o5(U1;hThIGyQ30jGx%ChFHvk8zknNF1a_D$EHAf)f_yQIwP>e6;}QH zdp}8ulAQ9ofZr7|)AiS^NwJgK{3)(Ln3zFY2}?wk0v3u>TSR(t6-|Qk3-BdxqTh^O z4dbCgNCHu*auFNI5%n8?AZ~7dYFT1N)d?EwkI5vx;-|!DtTEvI1xffs93o8uO%e~m zIR+WWAFq1<8N^kJdMVQ1ATIg_G5&uC@i$Avz{cd;eE8oObpOiL)Glr3uw7_s`YBaw zVUY;PxC>rXDi^v5gpm+TaIavCK-ICy8rM|!Mw3wZiQo-{AClHgdtyp5ap!K@_t_i@pY?N1QMWLyf zuOp<9kIunK4}akQd* z0fsY4PQLT@DA{LjKlm2S^;CR(fu2nq!2>ANPyzFSPG(Vae2ghldeK9aS8OL`7@=-h ze$pol&6i0pD1d25)Ep&h^ruQfg-J!UeRPi3gNeovR<&9@JqV&e{w>`49`5n)L4h^> zG8~|)kSHRcl&z5<4YQDju!#6{lF_B)_=_`DH6*W za9|sxJ~e>`+}I%!YQ%_fHcDmjCe#HD#F!la8VE->sBW&%s*zF8=*#eEn2Wzy27vba`lIqLpBWw8Wd*P&UXI5t3M7O9)AT z*i>MYrl%U)Ga;Li&8n3Tfr%={cUMtKC_p>sLs^)hf)Y^?M1>2WDhPrZzfa)5WIvnE z6y4m%wNH4Q_?oqwwco#pzh6Vtf#6%>(9sS$>XbOV&E!RhKy zXX4uGkl#OI+4jcJZ5HMKV4t`l#`L}Hledow)xK5M+#(xDgJ?Z4WBS+(;nrC#H>knU zjOFHSgK_Jun+V!kB_7a)gK>z1eK*EHpM=8vgIXkMutr}AiuVEX3^n|T$K%h4j<=`~ zB>l@>LO6R8q4P!>th%(gv((5&&q=;f$YZ1Z>;B`B(9gZDhZ_$r6hfU6g;lh_zKtJ; ze*+(jb<Z)0rtEr1r6QEp&PGDwNQjeG%>CG?{)9Yk3a12Yq5z=^Ic z$s0dYufMbg^HL@e=$2X!G$=H3c27dQy0wGGbaYAZ^*gopW1)EeF^7i_jr3Zl^GnIr zrBs%-48^HbDq63~EN=?eweZ zLMr~gT*o$h5}&*@44d>n&FZ!&c=CW57zoO-0oV**KMo}Ly9(~lTS6^X zL%Eh+q>xD1xoQXE^SDfh^I?vf>IZ8vBJ+#R4P1biHjf7BV5ks8bQrm(}Bs9Fx9cV*A(RCMYxpJ0n z**|`b@ZW^SvO6Ti`ixyx6{t$ogRv+a!htS_@^u4SBIB3Q!BO?1neFlSG&RE9E%v1VOiF6PGqP)MOq4cOhKpeB4} zg2$m#3g#U)+KRzu;+v9ksb*#>vn9p}uSSrX8sA7?>o_svsN_$fW@H9UGxA*J_|1s* zXjhNam>g3|*_o_Pf=qt$YSLV$0!1s^P`n}T;M!B4`VJa^BU>HC#G1_>R6=8;qEc9J z@lj9MI0-NzZB#YCs^3++=$@4t`GFi0s!9^YUI?5bUrP0Tfvkr&a@zb+p!8JNKISSU zWD(NN+-d+gk$-<#O+)Xbm=LgVNU+bcp>pl04_Tl4j6U|RnS>yliJhJ_&m;J7w~Ps$x`pB;jMDA<(av=R?_rMonmssOrNo`jUq`t-`j2V>xJ?AgqCiWTym zEY+p=U8#v#ne%k}SzwE+Y)Wr(wt1WV_nE!>g}UQ8#&!+t@Fi~0WzL6G_rPkt0M^ND zjdpj0&8wxOkb_xQfeldkcMPe@2^Xj9^`L^Mj9;8J_($%1Fk7 zvXvQ18BZY?T30G%^>b#FN$5qrDR#BU5lzDYX-tY#Mo;=MZ1uVu-65c^3_=&U*x}}~zQ-yc_PUqtQ7l*F z#v`=QmFmgijh_P;bbYvONZbzGe-7QzpZ08d{I|UQuJ;;W@%WNQUX8N{J6Gcn?D4;% z-cyhf%8K13vV+5x&fG;F4W+3WeZxpS1*4=kFIXUewR<#;1bmZaSU zyJJ(AGTlYHM<8Cp+?PxTtXd3v0Os?&fpYkc`F7>yI=^R{mw&uRHo_m4@r~gfk)vfoby$ zLMU)2WkY0Agw4x0Ci&%22}Qi=1y}O(B&^8g)~%?7Qao(BnPIxP`c$1ZA>j+LAnw+3 zXhA7T5lezu;(QRX>huj9BJNg|i%v9%h;8;6o+#QHRGSYoj4#j@ArG@W-YKe*17OJu zL)a}e+OiWg)Gc$+(qC-jtt8gclB1mMK2PVyeVFerOXto-(~OAQ1qj!7+xai8KPPT*b!1}bBvkA#Hl7w+uM+_? zCD#d#Q16YZE9&XZ_-SrHtlh|ETQD=giw>&4(M4&lz4idZ`Ak?_NV@%uuwzn6zwLy+ zcK-`If5W0dBI;YNWQPI-MET#Jy8m>K7q+u?HnDYNx5O(6HpcW*-PheqC3QdxHF#II(JADAdJvd@TbB#^)^71lTXPJ4XTBo9{ z&|q_OOR;OdrIoggm4!6>#`=)0+I#N%w#@gql6LL&oa46rO<+6XKiTGdSr3W>DjU8) zq#0o?ZUb5wx6g)MnXnIny@uNBMhv!>#kfv-6~o-d-%HKxZ{rNa;QQH6ix}MxF>yn< ziS=!3@*;t0J0MORzHd}u6zAQ}8yz<>L2mp~1e*)J2cOW+90=7W&EYj+&;AGMVBzjA zouQ+D6|K+gw*BXym|Z?^U6S8FhtY*!lrZ#S_3?X;FJU9STdPWO#WIfRkA9PB;iYptdvafv zGQpwFacan3i%ya>PP_$IccC-;W<5g_M_ypJix|8)0N5=-p(`iaxGatxttL@gW0&n% z-O_H0zD=#=mgQQNNwU@#C7~*1leA^HDUB(8Hcj1Jp=DbyA7W+toiAn9ovf_qsyYh! zQxF>5vr{I>$Exu{w`#0^KNfZgtZZbNyf8&dLF~d%OCiQ zhA5a!smSf2uqS(r$PJ4I>Pcf?J~f>kHby_JiTmifTOXo3Nsb9|+i*vrwy0)D8NiqZ5e@Q!Dr&-GTXOimm6jwvFw*6V+IlPGg%!mjp3?Q_s$pSE=i?l8JT7uNm83Y1=7`UvFQx#hldzy zO>biAoyWIx&TLr?o*>!o9k%Pe`n$L^b^p@7nlZB}VW9l#975XsGmY3-7GCF9NK27= zO2CE`n^LS(W+`m*E4#IJRcs533qUM*L(0WrU3Nsb?i5K{?c6DBJ1EtP3d;DG1e6e) z`b}BM-|96qUrNt~DjLraMib9s^so`iDuniD84lG-qj7dX%u8$ls)og`5T;grp8zu* zV;vqXv{9^D4~-r91_?MR-2N*G=+4kHtT%obY!{5Wq{t6`a9{t@HJTlqJ!&vz*ZvC( z!wF_W9;@B3mjof}7astDJTp5XkJ;|XO9aJRc>q@x(+!VqJW?JOD0);7`dA$rHEIc5 zCo=X+`b#S!Kl=^aV%QCg;s;Uo($-q9WtBlA+An71w+G0*RB-qMb?95<%S^(L^GFPB4;U}(%sVSpG*$W3AZ z|K3c0{+u6TF5O7NPhGYfbsn2tJ9oiQbhwXSurCn0j5qR_Um@y{%^gq9VrzxMKSc14!2lNVzowZeglu$xNbzzNmghlgT%+ z#5JW0=YL@U!c@;by&#Cac-n%w&#jDuOk;-m6jXEy@_h!Kj@1+W(1o_9&rE zsyPre$dvR-Ju_{1b0;6(U7uzB#prxr;B^I9uqL~w38ox~gvG^U4%V-9WlWZ2Z~H~- z%R>zD%hkAAP?}}IriZywD{SHV{E&R2QvO9mCC%mgt8Te*5@paJH?!v1>+NIZ#fk^L z$SIn(Ru9JkF1K7r4ZOnf#SNw~zZYGZW85FNV=@q6l`8FZNJwBs2e_Xkx7 zuc`~V$7BwQSva!!QboQJC1DN&!Jv#_qNvE?$-}S6K9>1q6X{0HdqzU2flwztP8_Qk-ZrTBysXsj>B}p9 zf$RM-o*-U*na-I4)7zx!B?gH-f(^Rj30{CB9hEkv*~Q2TLL#1OOtZV|S;wyhY^YqE zg(7c9rHgd(tQ-%rv-FYpoE6U<`n%((ZjWqsc6a8PAH4TnE6j1;y!S{zA+1(#xR8n4 z;j%dNq$g5$AXzivk3vHqTQ_67apkr@3>P{Pqo+>A#`wCIQ8>RaL67aHG%1GG9*o$= z8PSa#@Z?5#tdCdHDiNWYfHNA*6XqAu)(;m{xVd)8SBBMA(Da!9`T~F~uYrTLJP~67 zPXtU!@(ANk1L3g*yp9NfAv}Q_AhG5jo(@v@a*ut@??45#DFNml_;Q8vD0h#B&g@ho zS@NRz!!NVNY9b>Yp3B3AjDA+^RIkw&!|qgRvqTqEp7x%Kh&!L&!}pjYrSm&c%pHsg z#!$HtK4~Jw?wp<_mES>yI%_dwzuf6O0q=W?cQeZ$pB!d_@tLv~<*-ls6|MOc7lNpz zW1?^*C2(XP2*hgRt!FtUm~-hmj8XDk=#8CXva z`4T#lcL0nN&8vcwJF?N+@O{L;zzV%-&jg<7#>&1h4R6pEeox?7W#=U3*c zZitP6r9&b^2Ag3v5=h;H;=r0kN}G}vRI=lx<*<~$OStN@HB?54PWC?GEeVEynvH_U z2U>(T%jDX7(jU`7s(_>Y82Wqf$zX>d79nC%hhTTRm*^Wda(0y304oFH$Gj!4&oq@T zstz*@Fyg_%LflwczZ}*K^37uhrjoB9GrC3WrgeyE%XGvaSK1=v`v%pLv%`n5Tl( ze{4S~x5kSCPpL?I$dDA3BZ}8V6pJbBMnRJQ4g+6Q69VJ{&~Q`;lo`ZQV&(t?GTA*RhNQ6m-|Qk}Ocd6rmG z5p|Y_UzQLxWbzn`AJ(Raot)`Xsr=?9&2Y%v9=GSWWEuakrFD7ykFiu2_OyaKL7-)Q z-@3xlZ|4KD|I>?3LssUWn#+Ha+NCJ{vigU|Vr%&t#}*c28BVw9ZG8UUJ`l5g-DH++ zDZ8$LF+bcOAI-+gZUPmocKFF?{;VNOYD}jj)Q%JeIEx$RVQNm;5I)q~S8&Pq4l$_Y z012(LigobPcBMvJA1$Y7#`C2yy|c`(rF5$Vq>l45^iRLCKt`~B66g>Z-+#Otp&mAQ zotOUXAGp7Pg0q6>@Z%?8d3U{p_Q(3b)w>p@}d1Cn_sP7ayiD(L=MHKyg8&6 z2~&p5b`mn3t}c|0rgLj*PX*I+f3Sw@hCqylJ(Gf<>K+`krpALsoc|KmvVMKP1Nhu+ zbDM^XtLqIKHQ`BF8u+}Y-1{|bR}l}PC#dJ%=nr1|2+21js=Lq#!r}n6bVF<4A>@m6 zaZ7*eLDDkKCl|hC3syO22bX#x+4T`O$WmBiPfU!wdu zzoyU{W<|b-CEb8`0$+^L-Diuo4p}+k!izX3UKHQJF$>)ry^UH8e8Jkwkj_ z@)D&cZTghyYaGB1_g+4W>|JRnqD2Xgs~^sVzgG;`tzL5kQw4L`+sQ~{GPpk&dEez) zV{ozm_>!#Y*-`H)TtbW7Tp2^n%&g!D%b^@Y4ePqlVz`D`g$oWSPN6`R4CCq%$47-v z6L?FAOY_*{2K5r=mlS7S2KNSs^xwB1{#eHe)z=<0D2Jt-cz(#-oDL>PG~sJDi0F6T z(!LSwco9(=Pm*1qVS}W1CP=BDNY^|_>K{n>-@l(oo5T)N^n|8T$qu|DJH4`8)EYyy zSlo~!j^H*^|3T&S5AYNbRyK=&vugss=R%VIX9f8ubh=fo{^4ff3$WJE=%)<w(D`?efA1wLi3KXvuoORQ zGHb%iWBa80a!l{<#}|aZqy`s~hOH>O+TfkS05LAr{Qg}^Y;D3^U4?-vU#&Z199OaX2_OiTIUGZLds10uS=-FvsY&`$MO*IHbc=5ODCl!YovPwWu+u%cGfY9Gn#8q0j`!y)|uPD z7@H?zna8&4mAzn};++rBcF@Nt0K{c%qcu%**tNRZ&|v0{eTp|M(S3L#a~g2Av9F6- zv6nwJ56245P02AFii(nL@5Oq*`T&|P`<`AfD7V7pNdt>2k{CGX&E#bKWsVgq*=7B$ zh3eB0HS`i&=cNlp(K0o#H7n|~_qiS&4~s7TX zFA>ce^nP%Z&X%3Z>tb&i`^e_C;9A?3LO@h@dafwq7r8rhSpa)A&dg@*R8B*o05{8) zk2uP~)6kL5osJr{w+bV1s1}2bdf(Dv<2{ctz3gBAU3EGIYI8@jA;;7pGOL+3+8NRE zNf71*D@o+MZzTOC`X(JdAG8TWo^{ln)f!=G4*@=KD|2fB=h!K$JMJ%f;B;ibD;Mkezy_n20T z;Q}7@mr;?iY8MWQji_BOzjcdo8OLqBRi~2J>md%yvL&Qa_TWTXE#syhr57JpjwabX z&N(@nvW)hgdOd9$qV0M(1&eEM9oBgsx^oA$DO9`ByR?P2vw0q|6hkvV$fa)ZYa{sK zyLoP5c5CixBR-Gc2<i8r~GNh!+b)Xk-0x`hta&lo0I2c7EL~D=Bll_y+;2tuIdkkTUXm)df zQCi#=%~x_nLh5G08GOPF;s8s4xIz8?``^3R`FA05V1&jY`tD$@ z-*U_U!6xBfxT@kNwkD1S&i`hUFr@y^Fk(4LrZMBTWNC(GT8bqkx|rr_wY+A5{DM8h zAjoReutSVcIn({gBA5?^FJOFc2NxIGTrHonQ7yXMx7|3$_L(tb0z!pI=hwu>nVjz5 z-^MzZPGdWNKW@qWC+t<7^>zA+B9+r(58(MC@^P6Ryd!5&j8!Pokh49&V5n3!RpU`V z>Gw7IQ=tK><{F9)2+yeA#k;`58;h6y`{U=vraYOyrY4QiF_F^YJ`-~2yh77+nq-qs zcm`U;Fby>e_0M$I_FzHbf`+Mdm0O|Ds!lM}3?9fx#fD)gZfu!Y9!mijLP@SU1X|3Y zLnq@ytbb_Et;jsqnO)`BQ=LbC`s`rdEyJbelN)h|G>!a|T2{nQw@AFoaqYo8Qim7d%&2+!$YU%d;*8#Dn&28c?TyVl=A$O zue(bWjFv}ic3#76dt}z$YJ1{iXN7A7-n_edl=xSZ_6%MV&#i2sKpSv%W>^rVO^U^4 zxgG-RHz*6vHjp=pD56!+@{?kfK6Gt;4{LE_?m|iBxS4o=NtHz!&t(le*1I5y&kn!50qv727X2B}<(Zj^lT%1}jCsLZF7)C@ ztY^kcat)xJp|~R*U^PdMg9!7--eg6xRacXWj6IV1JFn2_x;EzE@G(!R;&rKqbcVGp zpwzbl`w4;E&d_YphW9<`*SFWyPH6;lYH|kr*sln*V>#7Wn2n$ViA;9?(kau!l#>i3G!#fpu-E)h$>t%wcE`HQ5Hr-fJGMCFvtnGC~hi(I{T zi;V1Nl9-yYTFe+Kj-Lm7#J&!%iFZ{h(&2(L(xJ&*q7msb6YpUUX+Nx9<)t#HCa)$g zl9jnZZ$T!>n)!c#6qTDShC<{7@g@=4&D)7^X*&RXo27uJ_jsBaAM#e@djiQ`XEuy>=-)3!CCuP?0^68l6NZw9e?;C$B*XEG?cA^t!Se4< z!Y8K$^cg#IU`mB{63rmuD(39I?ZQ03*%A-mEC@1Yb1SHWhgS5wgeR)}m?D$B=lO&K z(!65n)FpZ$Oz4b>YKt>Sdteuur6-K7MEMK9U3_}fOSF!%h9E&rDvGuY1a9Hkk42=H z)D${~p14dp4k=9?^DIHe+-o%gid7Gz*d@PH`=&^#)j;(p1*ny~w_B<$Wzu%M>N`gW z=@B$TS|T#5KvzYi(fE|nGl@`dQACu1QkH4HI9^}g0yiV9C@(*EPVDYU<;Vu58#Jb9 zON@DdO$*~o=)(TdYNKWpiZcb zY*IfOLfbhKK~a1nufTIEu|qNjY5j_10x4}Hkf`vl|1c>0qr~d}<|cpsrd)Au z_0et$fHV`pq>2J^Hz9h2DTe~ZkIG1O7)#hqikXFbY8Ewj`#VL;G=TZRlr_kXt613f zsw|Al1H8dhcgamv8u=naxgo9zdcb|TDN-_1-MTQX3h-b&J!jpcKHsWZ*-u-sPY)AC zh&+Q=nY&a}qhvbW!cy3F?7_nPI!(dN#@Vi=#hum@Eoo0jlg~(JscXG4>)d0pj$LAe zqN{%2Wo=a=s7Xv0xT>XCIkx$x>ttW1=u)}1ljKGdh1~*#DywH8O{o=R2BU!NGd?fd z96z@t6|xY#3M|ZFhs7rNTQw$dnl^N7g7!~*`zzT(qL@PYUkoi`hl`uE6PxuvmD4cw z1cO9DN_MI4U`|?d3N|AJrs_2^A3n?6y^GCe31r@+W?X7HUdY(iyl ztwgM-{mexsJO~CD^gE;m(YdqlLyrm9<8f2ixJ0(C#nqFo``{|pyr&N@EEwdta5=-$d#6t2(% z@{lMTH*6x#2f2CMC7hVK#R0FPAHa~HZfAB#p)Vc1gOW*?rK*W6#8>iJ0Y0PyVZe!7 zHOhSiWAUl}nHWSMZ1U~RPUow}lzbfb1B^njaP<#nH*drjvzb%(9`$R_Mw3eGiI1?~3 zV{?n17F|su>B@D>0VOqa0UKT|LG1=;lgqV;)B|~x{%ZPRs>Az^{-2*Fh%7{;px^(S z{O>Ib^?#p{{v|j|{6F8#{(aRlC-;w4%YtpE&97n*DM1xj7#rZuWfAXL49PXA10}qc zoBjo7Zi`eJX46j55278J#X$_C7a;y|_tK0fFk}g`=PYLC=bW+Z_lxH^7$BEL7zzW% zI3B>=;2(>2>-`=y1ZVfMfyfAPGV9QjmcM*5fqi^_W|eJr~N&W zgh{+~UJ2ng@?bnrDaI1Gtr(8(Ot&ih_1({M5b4! z2o{CrUtUKU=XsJX%T#HXS;}E0q(;RQ(5R(8qDTKWxkg z)iTtCd!$+L#%dp(0kr7dgr)iuaBGB}f?9+h@#n|NE_cq_Ar9Kx$E(aL) z+FIrl;(3%La>@e%$g1=Sc_~7iMdyh14r*s=nJ!J+C|_t{kpH^4=@9hqCtSVrzH~R; z?#jOA@9_n_!GS=1amUaHYX*wDS#9r>Tg+a)zg-j$%CCC;HXU`Le?^r?Ss5rYi&-2< zg{@T5Gofr{S}09Y)Jx0C=lbbkdAN$p^ux%OVh1f>dxe!ut>O?4UpYWZ9-g%oSr}LM z1D7|;j>FGUgcWcVGI=qB@zjxyNv3uP@O|M>8pBL4t>sQ{5!x`Sfsn#TwWnxq5{KOy z7Q&1IvdBSJ&bB7lOje4r;+l5XL)}D_JkP>D`&ctr>odKPcdj6#qvx5^N{ik1pre@8 z{h{pxkX3$tTY>x0ZEdJ@E7ifK{a1?H{zbUTkamzOgKz&Q?PXY7Kqes-q>u{Yi#c=C z7buwULuOj*r*wi=sM3H#Cl7gd&eJURcAm|8nnYTg8c!!>fx0mhA zALzwBkk+05zkp}#)-TulyAXkY&q+-GOYq3p85uZR*xCLodQ`OKkrjV_!Ed>?nzTO) zA>M*m!mK({>uO2XtJyRJgwc}3$V+QpBwno%`%>etX8X6^U2oX-$Zce+qsBq7 zA?Rv<%r<|9?A&}e$l45-aUI4M*(Aa0E0ySObQR%Wt2=B@70v)ZX7l;c`Xg7c>?Ijj z{W_&vc$-khfxRcWRv-O$my6zFWL48GpNShDBOJ{Uwe4n#Qp^{4JJiOY<#ZG;x1BrO zgdRQNJ+%$Ap5J%M>ZD=ZeQ3gW8F$T>eEC6c@GiKl*=VhSHS*~~n0vEQvaJYodi`o1 zt-r9MpV1H_(sftt*6DHkIDCG2%Pr0_(%NcijUe-=3icieN}Z(%OOEiMy%~Zy;6f25 z3Kjh{!{}az{kD3&a47f=@S|t#@Uk~%2Q_5)iw}zdoeDv7?RwjR?%V8I-z9`U&f#OT z=cpAACPDtjwYEZ;KVmj$PN5`-!rTTNs@d=-5si8o^gTG=DVQ&D$Uezf)AzU6`v$mtHoZhQW~^k-Tve>qI{G?M$MeB|03%n z@63d&BKkILmiQmZDF0Ja{Z|NcLAfidE}vwjvelkhip__SEEA8;JxD*dh^a2%AoPA@V@4$4jPw-w>S z{ClCl*$*D-T~6ScZ)fP|WVZ={_J2~q`Nl2*N1zZ zFFD9NZi4)ql?S=Sp8~yMbRUrX%eTnrAO5-LFX=FU19LlXYG2rK5jt*QK00B357z$p z$c_CwduxUJmon^gIO4BkpTvjS2=e_c_lFyvb>H7M_txwC+utuiFk}aDcQ5?7pL8Ek zey&KT!E|W?ha|GY&rAei{y6AIiOM6Wa`V3w#7RbZvUTXj$%O?1{DlPF=IhhZOQ!D> zijuTT4YNCL@D^1|ZMkZe%R8eVXUB+bXg=LNEL^u`I$MF~(s_4Cq!R23)Z6je21I6efUJz7CtC zG={_`?-gdTXst7H#iX!__s)R~Ls6j4D);IGd)M5~%gtI8$R!nRjEE*#L_U;^=PWp9 z?l8vIet_Sf|IaJS}LTCh&%7Z;0Lu&~AJDC?8F*O6KC_OJ_xrm>$F z%0_G7MQhI)qHFtAV@6Dy&`0W+gM&M>Y*B81h4UMQDcZ|2IT zx#Gf=Pj&5FfGdpu`X*xM|u4y_sbMBEt zmv|P!rB8h#%BBOT)6JbJ;nE|q>5=ht@gVf%Q5)axj2-Eo6;(QStPhP^86Ro^uS5{& zUKhzW%$lNm%d$hZDWa_rwK^#C*%W7jZSEIo-|u;KOnv8icFK}%6GjadyOqYF= z%01VG&Ug2JydMS&n>@aQJ$sS!?iN90H{k;RjP6hv#ZSk15H0+o2yCQV#IUxyBR*~H zkLl4Mz!9Rb)?8jii+B;P4{Z^M9^q;1Pe@^9^kYHO(rm0D)o3guEejncKv_*Xx#bXw zqj53`E_H1wmAkEl3^x8d-Kh4u{ARgs7@$8@<)4xA?T3JQH?&UF<)GQQSAXm@J7UE? zNE9$T&UnCNp035@2n7(!j)J~RtdI+8CC(q`np1>k1OPGJiaWUj%`)H(2u_M z!r3#t)RQ74@o4bVa7wMn+4eWM&=`H!_ooILDmSOJFt%$&*YoW!6xjvhy_RM3x6wtH zFf2r|sasKR+OIVJe&X!;C%)yC@r$_0LF4v`%hnBIWt;`}vjh*^GvVxwTrrKEKQBT~ zpATbu3elxgHz65;UlQr8yu#42k0ajaqmWx%L>C^)Ia>*y!5;tufJd%L=L<1_%3Q8c5)hADFBJ}dO_!FOV-&qm@8Bx*=yBtDOt+)oGd0Qyz3%%fXiSp?fBY%Jmc zHBFc7v-4L-qQDYw)Z+38N?30t%;S&_lgPWb{Tk{2co0!8B;OEPR$WNP(FW~DABes&bWE!XcnrK_cbOvW&->GE9W^_km5 zv6Tv~=cE3fs-&_SNo09x?H-<=$Fh~R@!GfBdTO;Tg}Cb0Fg|>^?=}%ScV$uF_0Qn}&a|%m|U*!Gmj(Nvb;#9ozFeZ)*4jksWa)iLT)}L#WKXAuM zboeD90tSkTSuxAtfT$f+#%~g5;+U(KJ`ez)-`886Ea}c)D!r^}G(0=(;Hsxx9sND_ zVPsMu=8D~voa>nGMLiVJhLyR-!$ zWw58ZVyQ!RWvheS0!K4K2knG8CCnoSU}#X~rTT9N-W%$XlftfxcEVkfr!fJ4g2DDW zfilw8JCqX5?7zEvz5zbpRQj=rul*?Te6G zH<}f0O8r!MugqLTgQU7%@Udt~%GqT-HCQ*BC2rc0jKlg~rHf(A;zTva)|6}hv5Oi8 zXAjj*%wowr&kqWN{q}9beBj^>*ljk=3<^??mY;T-PXgx^g~)nn67(xFd%4??cVEss zIrSj#)}M`fNED=>sA>p7K3QH_lE=TYfo%oL6gpz0_Zla&BRI4{Ss`EyNgWytnf1!x zUtXO&c?5S?BH7%JVSVq0`JCuh?0M(|#|v{xhX@O|KdjJmn6Cuy7OTa6An)qyy>LiM z+GaSF_3Y1UJ+%R~8>E%<9LaNY02P{Hd1b=1f??0>@aTHgKs|`PANHp1rkxbGOS-#{ zWQb7ja)lk-fLZCp7cz$PL@>jC;G1@x&xL#Q=Q9>x6KY7Nfq#beu%G^Z02Qij$}CIT$j-)F!+aqAj6=vIMH9tn za6aE`Z#;qKCjGh_?%x(83&C6-W$Jab_;cRuiuz@7v^`f4!p|r>7GKXr!&oTD4^uou zWnUFrHd?Q>CBHc9f2}MW1B)|hDzLy3_QF8@$kc=bz@%08Px578$u`lNNLuPJiTkSo z$*NXlN!r2Wt&un(^jsZ|rZ-i#Ln2Pyk63%TPs`rqy*@KtuLFe);AS0|g>Dk+A*)Ub zK(;5+_MpCVvCM|6mTVzeq+4wM-%+0i8hrw`Oc-e41B_HW*-qny5?Z6)_kkp#K0bJTs~WC(RXR?Fw{LZkGoY^9F9l%CPY%CdA~Nm3~G7J z{1_BGhbk`1D?Onnz--hhCwms#9VA9O}tM#ExhJL_1`qtz*-VPetY!?b#6w!)k} zX(yv998;@#7|-OV8m1Opr=v~y>9T?iMt|Op0;-X48k6IanheDVuC0B|1QxGQuY?1e zrko|M;jUVjrfvl)!}x6MVl2~l&<;i^+wyFz=|OD_a+F#YDKJCREz@GV&nSUzJnit0 z>i$_WXt<=oNEx(WnMCw?E3+k*3#--U3vgWs*XVy!1UU8?;Ai%XI=)*Egl0eiYZl1+ zdSJQaCqh`9aMDPk)W{_Z*ySAElMMDe6^ROstacA04vHpVJ~XnBG#lsX^HABx9~A#Sh)=GNa1J)iTVmGTz%nZM9TLPJRS^iqN;) zY8iMt8a@3YuA=%T)EFewBlB-l`A%WHNwHwZ232$WFol74cknBYR4 zP-MGS2}1T4Elo85ILu`)@tS?IHj_OCGo8|gMze>EQ*=?vzN*8*LDZ`rC34;dZ09#W z(jA!9@jVJ92Y3O%`F6OHbKn@YbnQr*oIkxgQTP-h6TW=7!E^FPH1jnAbPo22;kR6y zdp_8hl8%@vTY4IFz6IfBkv+%hb4XDjIZbAF;MP?w!<47!IP%0)&5+IV4Qazg;$@>t ziA{+n&SV}9r!WO_OA(d67Q4^nJgETis@$3tunmo@8pS$R2l;=P8w#>yuY;7PT6H5QCIMUQ;tP@pqGCCob@{$fTvU%O(0WsWme>)467tLNeE?PBabm ztdGH?8gufYhVDMg)TeeTZ0QDzysGT4cHu$FN6Ept^XJBM&SP1dG_&z>59{ehPMr@^59Fr^Lpf1|GF@;q@UU$+jSmP}9m=+aDJWe7bVLu?Z7`Xz3<1J6>`EKHOBIBsp(W>Wum zET?6nKTQ`wvMw~9^1Zy2%4+VQJyFe{sJ>*2jw;{lxoU}d(0*xAHjBk)ObOwm$<%?% z=H>7B1ZRc+wSF>PxI(Y9SKXKSdw(fSrG4)zx045~>RR%pV!nEy5{U=NbZXXYf*X&X z@)02PVYeZyvz;hub>$*_$w7;7yG<#6T-7pX)sEJ@)Ud{yx9gc~qM`jx1## z%hxNJ&@GgFAmAEr`(N0w#Y(=!D;jU}UtEmZpQ9zQ@Fu$%*i{~*o0f1)8u!;b*?`E( zz6zXQMwdP)%sbGcr3cMmihu9a=G^-DVo|yP;n|YK{F3$+;*av(khCIW2R#A4135;F z(QUlyaYU6P?xD$Pv8QuX?|^Q*3bel4(B_8+!Uf_1O@R1m^~bg9Tn=+G zXNv0_$z1W22B!5~p&pFce`9YP3E+_%)lvp`&HR45t&P%C13R3-E7SW0bEre3)H6%} zhg5(>Dnx)jTr4WUT4NXGDmD9%+MMIuuq3zC@Xb#)Jc50wcs@G&+ zAV_lA%!$Ek;DrEiBdRqpqJ0t*#&~=zf=uCL^SWO8e-w-(rXhs@5U-&b=pNI5X|;@DT)R=q9Nfy@JyzAQ3FX(K;z@Dc(6u zTEiBV$Mu1V-BBi}o=7rAFGAu**2l({2$A2)*TfHyj|ve? zrwed*9+oJlBXQCTtAy2KJX6HY?rag;#8TNcD?D~+Qft#`%&FB@V=^MOA8*8ZWsa}z z#kEILCWGbn({k12>sv!-!~Gt)GMnoYAlQnBS%9eH95NFu$3#2XDQk9CpvQK7XW%2H z)@UY^19yA)o)SsfE83Ly&_qq+BhnlKxX+DyYzd6CX$7K_uPe}^kBi_S^vA!tESBXdbK<-dY z6j$zSz3ePHHCSm#e_WAONc5br!J=rT428mLa`{*O#Ode*_etn9q*0-|L&2+Y-JYaT zx(p1s+&OaU$uCRbP>)$?qG=`gqO*bCnTA!EX%a$&w*Ngqn)iBX6PzDG*BhI>dxXVsx z4N^M3Uu6xJtRIgn7v!j$(r=I=+EomNZQs4LJ2U+2zKEE_ulBXMVBMGiB zq+Y>b9IAcIaQ;Li8s}%z)PB& zb08Ug(#;^2D{#eIy|;dDFj@8*W9!9J@}n|;_%C+1R|&mGt8OfukH3vnKVjRCeQJMy zN8!A5ulo69A4MFmk)>E<>s5LAr&yUx>v2tWL4Ir2LHZ0EJMJ44>V~`cI)v^MM_D`f zo+3Wem+s*wkX&Xg{>jdTVaO)oNb_Y{Pt}qKOzz7CA5}OXEmaQL$32}}uD4NWT0|X@ zicQzjaFFH0Kf$7YD|4(tO7$akzHxD4$VIi<%S*hv}nx4DHl{ zJ_L`gu)*!?!M#Il<7ucek!%ZLj;-tEFHEW!4d;w9)>b24$~Jo6MW0h%U1_= z`$y&Haa)omi^S84h%ZIZr*2GaYib@u1HZ)Of-ob5!6OE-Q-WnuqB*JeCkCTwqhw*0 z-hiJTf^0#L>C8Ii|LT<)7|XesAqiA8I#+WE)U;26gUWUBL1g;59LL z)h5+PLT2bo_1kBRrw-m?ThblF5Du&gB`^ig*MLnQMeN#R2dnNubOcx}1h7Lr+dAJ6 zM-7>gk?q;V>o`o~Y zcoIxzH+B&Kw2~ky+A94YF(jHEfl77qNRP2uzQLv@6XepAx4AH6o%*lbb${_<+<)dr zy>m!#ck4JVWVx7gM zBP`aSu#`Y_Yg6C^r~sqDMWgrODOx<-1gX;{5wPvtfOQQR!_Pcg~ zk?uO#Qg8L(TK~m7g=PKEFj+0o9d}8e2o?R8EaO(gRleb(UUg+Q;qtW82Pf-5C2bE0~)V$>rgtuv%_lvwwr^0Qg(J^J|5 zqp+$ugkla?`D-Vh5eG5pQM~83%5uCfxMEPG^DYK&U%{n`;tToTLqn;pcx-Oo!DaVf zQGLbw*y+#6rTbP2!|Mf6&FW6L@nw`iw#5KP<02(mvMNNB%U@!uMJ0AwwVP+ol0A5P zo*;^6u6iMhhklu5OY>Q0$th>a>d86*RWF>nx7m91U8Bg|po%v*CH>EHC0S;QJo82F zMTaoN5-#+Ye_vg?q`&QlM$-$We5N0K%f>Qm2JBVC@&pgnXr2zlC(6rHRFfB+(KH5(Wqw@v+wt+fY)0a^6`0Vpw%w_{1q(IpPqO^8C=CrP?<5MOo2U&~lx80=US6m4dz%Yl~ z#0*o2Ywq^ktsXmcX%!k&q28Q=dv-3If)(4xTszei8I_pWxp#RlEFPCO9N=G3ljA<@ z+%LGnd+_v_K1P7g(9WUhnwUQ_dl~L19QcwPwwN5d+;h87_PwNIA?qc-t`0r91Tyvc zjyI;|7>?JpcX-agvgKu8;w0&#C2OG{`w-6}f0x3;6??NMMfFf91=pAI(dGf6=lG%L zN^&Qb-Ds5!jhBK|7ZbQr!S;KYvRfA;ywET1DKbOp60(vpWAYW%zJTIHZqKk2rt#CJ ziQ}e8d6_}M7N0UF8PiwfJ2}E+iq)S8mKC3yvRW1GpU9;BeV*ZVPeG-qr~jS7jI(w_ zh;mt%w$Aa&+p$tXY=4cYERnEPSQNdNg$@gTFz=j5a9ofIAIJBL$qU3mSoO;d0;|fr z_2u%W83bEvB<*H!Z!7`jz1`fUH<@eqo}F_7>!VD^sC<}p#hCYd+cd-|?0bcpWwjbj zRWzR2f zd!Mw!RP3BBArv1tI)ldFnCQW(4%CUz^Sc@yDgX(SUIhys8qe&CC|kJ137g=R*U6ZP zk0Fg`PMzd~>HbP`0|mxzgj00ly4k7)*<^lPZTElJCQM?kBlSO1S=&5|b&+U&!vIDbz)Q9B*`u!fNF4E)=RW@wfagTw21Y)B zvu8WkI7rkutb#VrTepNi^}ww`zn|!{^GEmmZNS^g8{Q#u$A+7Wzk%fe<(r#N5%L)j zbVqHUcQ`3TTbb<`G5@T~R5L0o0?f6Vq&i+v#AhLVZbm+<-RW9TAi=I}%Y^92&J)y; z#MU5OAEL}<_IkPcXb`9pyNH`r=9lL;EK4-^`3h*`5Scr)9XUE%1sPc1HTm~Ox=6Rq)uV1+TU-{Pm-P8R~or}u0B9bcd7b^(jk}?A@VTo`8CNQZ+W20|FSPnm8 zWdXUGMKS>wP=h2Z%is&j`kVHIM@XXd*Z^E>=`@2t^Ba_x?{+5ItSK_P;uRZvvtSP=*?aW}L(IFLHUs)7c6vD*_ z2Ev^!P!K`{k}IrPyU|nGNozCKmflIMvp6aK(15_~oturr=Sx(Xn>5#IgC5pKQ1Gv% zseqvEoW?B4g$zbf76nSO6InSe+DK>twKNTNNff~ni}8#mixy-j#rP;0&*tMq2i}P& zXCp#R`|OQhr}f6SX!)(Bv!#DgCg@-7RdHvHMecDo{M~?+nRQm>`TWkfav3t{vT^3; z7nM=}F<0JjN}x{a+;SOu4W$ zjKKW$zl;^o9mnX#UxF0L_vI^Pr6j60QY`IfYR@7x6wxgt>rL3x+H%lC zVcC&^hP9Uk^bG^VLydy4;E4GdrUt4k<{LKJm1XFEz(BGg6zD9o+3t$Y60zU1Fs7rH ztoFw4aJ27-NSo?d`wflP$WJ1F#U5A2<(~@T>o0?OBlacx6AVChACV-|SE&yMYBD0h z#LHPJYc3)IGPgDY_1)VH%Rt{K)$YR;gyTQR;JlW@4Phgv?Mg`rTjhr6RLc9P+Uol*uh?2BQ&)~ zZVzS(;BcY`{p5MCnATAbtY-e+X4irpp$vr^j43MDh-+l--e;&N0#broZ*kQdrJS;3 zX}#*uG$$5FoOFgQwPwcYQt z$~GrC%Zk9^@9TLW_L6+?JUk^pI82iF*e4d<6ha$VzM$s*%4pE{)lQmFvR_4a0V9gX zWtr||5GR7plwTDTJK_;vtD0T00Ebu4#D#$@&!pj&=3L?h9%be8@qA!jB9F%6ppYY9 z5SQwyg0@%xz1_AYotrhaW9GqL6*_HGH!4@x_%YDx*C}fTM7@vuEuUy;HJ=vU*@C{8 zu@Y6!+`D|ZSgVM_zrDy|4pV0<>L=X%ik=x2izV+zY~vXEOq{rMt^wiMu*75Y_Fex% zH!*cXMZ1B#oSyARXFN#hcw)8C>?8iv&Kst9@-=JnRsZSG5nDY$UvPlK?e}azhz@wVu#x(dH`oDkcKBIa&5va1LdMcUsUHj zi)qj z@#ASlMDptw&i{~_tt|hy$K!uw=0XifPwYddZ@x>0_VQZG%0nSu0QIkW5 zAvnaj1_?9UFB@a#c8$ou4=UsC*Q58X=dJI~Yi&c<+sNW9pc<_>hKs(x44z0nc!QiD z0dU_X{d}i4)0`iFVZOtXot`QozG#MyyU%Yf(Ype!&+dFq&V7b%csdMr-od>82w~HS z+z5GniHE2fmJCHJFUT6W!tzD#bQ`>2d})TL!hXoY+}|4h=8M+P#qH3<@K)9JmJj_N zJWqV#>!@Pxj@X6Oih_6{6r?Q0_XD9MAt%7;3r2543l(P$1|Wt@6sAbB55|=JlUkfK z<5W8T!)D|zYz`rBjLxWdYJ5ts8KQx6bV8pz0?>geXCLuYufbRvkA$b<_wg=nQD z4KLKuO;(Z&0D)202&FY!*frO-p37AaK|NeIA7K<)gJ~6|w;CBEK`P}@u_jNIxV~B; zj7bMoWHp%+dKKpECX2;v613Tt|4uFLuA`wW!R1bodM*lnujrzs;)^-OB8;BmLJ~u= z>VGvVt7PIx(53qKMEpJ<`e8eT*pOsZeLivUwtlxH$Gf@hY)QY^WJABWd!yB^UrE!) zsY06P4FmtqlZYRl6kbr^LPDc+0|5Su1WTdKH*QuVIv1!yc%_;iZ zapqS5xMHescBk2GAoib>0Py-y?AK#6n%)IODeX{dbuBLULGS{;i<2FJHGMQ1!jwxx zoK5-5C6f8k4={n8+cO^jog=C2Li#wfau3&=n#A=)_Kdp3>4!T>qz<*N_VC^h{lkMDI5~ODS-eRMSGbRrUn~;>=QFI&%+$G%yYHMHuppK46-{^`grr z;Om6VM!(%B3Gi=4;zv{>J`XJr4u?BR6y}YepI7gU+gqB_BDFZYllZ$yUSStglnovQ zi$hwVK*901Gv>9_N>{b`xAFWTw2txQy21U-=%d*ZT@(v-!#E#smIUP6K1C`c6>p`iBB zTc~G)_z5)6Li$+2aLYhczl%mErWe9`>1BgZ_KB^*iZ%r68V9i;5*&Lgd%`5iqF3LN zW(bnuUFNtF4^<3@=kW>Up#%)z?zc)5n~*>u8xoze!g=IaR3d5t3jjI3f^W1wuENYZhZ5>DWl=#N`?AGm!h#kTpa7jt@r#sk1hZ}<0mU^sbo~|;Da4UILI=sK zMhXVsY(!E~W!DYKWsep}>I3X*ewPilb!p&wPXI}5#%3>b%(9VUc@(oZ1JMYo)B}qu zBvJWOO?Nm{Qeg8aa4q)=f=Mn@JM}!y%p^|w0DSFSs#RxAIzy!t1DgdvvjrI8R9qT| zb*_k=i@}m!B~MS$CXH`FPxE%0Ntmn~jHxWz2viKVWCFB1qTAO~G>aEIJIDm@GwSd3 zH{>`yS%q?wVIkXPgd6`s1 z2uZhKrVwvU5s$Mq0Ry}e_4G$~iD5JTk||7WIa4JnTVRPXaunClxy8Tn%#{Tp{Xhhb zaZNLodg+#EXwYe^K=;WHSK>jGi9QD*rpmMd(CMCOr&FP;OVLLH;+3k7zNMVAVuLQS z8<-wNEegzu8p|2VABH7G<;vri7h56A_f!O z+Q0u2@keZ()v!>@c6ANS)c($EMJLkP09qQH6T(-R^);?ht>l?~FS{S*M1t=Dv}cs` zwUSxk!K)7|8^1p}Svx{0Hb|)ZI4=Z2oekmhQUW?xzi(d?9cRHdhF4)<-5^bLG2QX^#PPq$Cfhng5cDVhe z?csjzK|?5z4&yoTv>^5gdu&*w9knpls4&AKqVd7p`gSwvS_B*i z1h1GT$dheD9mqU4-XgQKUkXej%_}iy*!s8yhqT0*KQ?J9D?3|9{vK?-rBLOh@KwGP zlYTkyT>zvVi+)K$>NLy55F3;&nPCSh=jiaW0*g8-kwcS46r>!DQND7?3Rcv_sW26f z;qQIPXdQ}{SKgg9vR}rOY1sNm zzF4;%zm7lVZ1u04^%XqFKW3XkS3|7%LD-W1{c|VG%lcR1C5`eV6~sY!l_F)uQZ2-Q|a`kmOA?!f9!{-GtaGa{bWA` zra)<>Hi=2w-2_78*g`zlpHg4BctF6kSn#VUj2PPhCL zy3e?(4n__>+Q|%wswk7xa*p+Ou#RfMJyEZ&6 zhlfA3%7{|mOboW^;d0#z5Ludl8*4Z97?T2mF|h~Ea--X-T&!>IbsI`@Mnp;`b zdNg!;|8}ILM!Vg%`HBmeA$a=v-C`&0xIO98)nvawR}6>iRH_MjEM^aBN;IEQ`D45hq})IxWPXAxtnkj$OwM16s?tQ*@tT zkM3LONy{eyptRGJ+efL_5%J0mDP=q1xG^@dqLZ%M4MFGr=fyM`Y&$BAzcMw8K`l9% z>#Q^E^A|NCQ7Hln6a4nva~wOz(u2Z~Cw}U>%4}8UfO#gb=pLP1#_eIx4`0-Gf~H;N zp()vu#Ohj>S2GDAm+W#Q-^z8xrnt0EJUgtmzpiVO+Ab|;I;Q5{=(#(q#(6EiG$t%G zb5tgL2OX?@;ZE971QV#dIz5qo_0ms9QTM#s+ZvYdmOPPiJJiR)X(#({c}J$T(tDPi zsHJ-fJD>||z#LY!kwQ@Y+K?Q~xrEXsgRIliw9+-E`ONv)FC32_p!>&8C*MpADBVWO zk6=V+jHvS-X$8RJB)*A=eQ=QbDxx2kh`l(7B9aE;;i3Ae{vHKTWJZ*{JsY+PMf(X0 zJ4lSbvy)O?1&wp@8%dhFb~qM5j|xmoR|hLnv-i{1-qek8$W*bNHyef|p4LG)&AR?w zqL8bcQyx;>r$(acwNX>sZD7jEz}EL`=TkOS6?BAsf=*=_F4Y`L^6V=(EI>9LWFoK1 z_e^TjpxK4Lc@^uHoteWka%c-T^W$+P*qZ!GE5p8MPQufkJ6nY2DN}O4Yl6ByU`roo z%%B#K!_*s7s52cvH52S+-q$f}blQ?hLp5$eyGb74TOYUmTzC{YI>&#XGp0Mww6#Jy zaM>bivXZJQNzAAyW;?Wfr={OO%9_n3xB!^3&q7)-00x3YPK* zNI{)YnAB~Bj3!@l;p#u4BtO|)7Cb8-sbs5^nYD} zX#3HMPN4P6tE?^?{m$zK{;xf^y-TU@-On0yPh3v2b;R{FCAn)O!)*Z+KKx z_9xI6jF11@#$;UZALES7R*&n}WA5jSV~*#q*J--$-z}l;h=woZp>7)zddPU?`U3r% z#Cd8`29V=+8}m03*vkp0^T;YU>QLGF1;LB#))e<{<*Ej4D)<#CQV=>oam+o%)z+DxDDBa$~ME1CNW>j?WYa1 z9=G6uBkJL}d*I!VgJ6E6*-8f279)-$jrFROt>5``H}`hsqK5r9)QxZv2(2~@@z5m8 zF!9WHJl)%qWAftBe<;Ecg6xXzGW1 zFX8d3rTwr3!I2tPtJY&=n^mxEo5sgsl}Rmo-rGU224u~*oVpzhT|orime4*!xIlQo zKHdlnQ>%j5)iaDj={vgF?r;o`z_}(6-v=IDLky#QF@hk=cFJx}o^E4UAJ844mcC5a z*$@LoMcD*%(e!=I4;j()Tenbu7A`RB4@5+wOdM;%zA*pEd`65!YnPk3Q#x&3nt6(Zg}!5jiI3>k%y;5E72P#5+;phBqs8C3Ygtq}&;0<4Vy)`n()|6>}a zY^M6ZK!w57@c{BasD&#@l!CwsEsH8WYLXOszfI>A6c#uog6Y{)L+j<_x*tp)&|Z|M z_6*CG5boBeeVQ9Cj}l#R%JIZ6)b#>G6LgO`1polPkkWEq}yUr;CzlpZqi!!U}HX6`1Q~ zmEm5$VcOq0QzMUQ+J8pt!-dxN(^t&5%Pb+rM&l2kG4zSN@GRNkrAwaUIK_^gd*?1q zQjq!2JoAedYfV=t1&u~&N#$*AfVj0oXLFSDq)kRun98D5T9hEIMoIz&*bx$?WK>C9 zI@|dgyUD!RuCgQ6cVd0~%+ryPNau?Uw|_0D`K0=Fe_a_j3I7oIyrxmm9CBl zpRxOI+EPVB>V_@5KR`kXNr#+Q8JAZ9!Zl`sTxbLA4-&)+Ih>nRnk~aPS2H6$`S+Td zn~Os|M!gozgcFhqhY>|J$`4z|ot z!gSJ$WW?rc3t3gAQ@kz}u}S7uJunV7;aJomZDNOP=~PTLEi<7;oCNwM9wD-fPs7dj(Q=@o^)i)nQ*G8 z%4?DH!JBL$z0F&CuA^#lz9-$4*@SmQxYgp#KzW%8B~@da$A&2?LqTu+-4d0 z^nhsBrnwM|>Z=RpAzio?tz`DS#m3_fVxLw$6MGa=DjBJrN|7#qns;bcHp1I%a>p1$ zZ>mX$15oull`g7{Uf=R3DJccPgC)TL{7L2)WNzxJVxW-gLKXR7c|cd*Eq_a{ctugn zQ{ppWzcPGLD=qaFQ47BW7>oWcz=zm5PM}(oeQ(lBmCQrf8fIqzWP|d;*JwLNTLhwx4ex53)xX zw5pdzi`z`G%pr#gbCK`hdI5hqh?p=1O4ZM>!xrQFfdhXX4uZsCf90jpl1+=8hgq7aZleXOh{$55Wb>O^WS zquG?IJoAUkB7-fDV_8zvP-O|{;ISpK29_L~-;aRLOqe zo`qd%{%j#tYD%T1EMhG-LpstuG?VqR#Y|Q`j{iH35SgZfJ(gg+X+s}0x9SQKbhlF` zW0W?UA-Yz}d~O1pg)}~ac_@Q|h(q6qn&Z8%hRcw_)*_W3oKc206Yz^hzm4b~oyFOS zPSot4aF?j2lx6SsLta2r6`)N)j`)l+PI7uqVMg|Q875?yxz2rS#`KF;pSAT zzab$KjR~0+WJM&htidX`7gjX~MFQK%AAc0YuOl@bfI-9JNe-oB75MZorXUDHB~OC* zoT@QNNYZgYd4y=)zFJj4#!B13MpA8YB!|Qv6l<)RQjaqA1X^PAiySK|>|CxSXC9p1 zOwMUzQq9?*#-mo;4^dSP;6$#5QF0k$VGOf83SpGw>Jsz-s1T}Ol>mc2N@SRq34U5V z37u8bv6HoSUqd!A-%{r@<1#e5H|#~0iDliFp=APGH5a@;2Bof2GdMZsY7UCv*z8FE zkaMf^6_d!b6zn91HC;8uz*#9z)FcV_t{HXX=iHwTDvY$Ms&{bw=eDZ$wY8LQv!b4F z{p2RbC5A&}Ol{_o;F8kX{_pw6n zX{wT(c%pTLY9spNO(rRt%Dlo9Q*ASZ=OQ$kMqUUIn_`P;DjnB5YPjMVXvb33sB@fm z1$CB!B230#cgRhl?x^rwYTlJXJ+oXGvqUv06>H2S1|BqfUs$T*(PDG80T>$?J;q}a zq^V)tDzlwIpA5#+Y3C!YUJ^_qV8(};5K3ALk7W?W4yzbLO&=UPe;a@0^msDUCdC~` zFdI*`ZTTSHns|f+fxeU+>ZalI9lBA1hw=$e9@@Od8dta`ATtI7Tm*+n!=pF zVj1B0SO&_G1b~Ce-Y5mZe(Vppy-)dmNG#Y-yB)3xjq;8md#gTd1kX8uD|h23d-*rrUHg6h1v zFS#&wn00ftpo0K=J0|pD) zUbD`I3s+Qjn>n+vd1U~N5BiZ{XOC29b z-U7tpiL^Vz-$LQ}yU{BW*1=UO;W|&gH|i|utX(a42W$<{tk7#?x`uF?F68jnXdYW- zQvdNb{ri&$*iK45{NI2F0KO6kKKdOuY^zEN!9#KE#LjfkT(Ak05#YnfV6JVFFLTCj{($=3!SwY3*2?f{S&>_dAMf5=(xjy@BiASerU~lC_w!BRf_mO8rA+3p8ti< z6{!lTsdS9uO;^vTr4k7?SkmIll+T?T%HWSFVpX#P=3iiC>kF;LnC@~#K4W~EL~Ay` zW^86@kya$pwldVfDQG$G$YkZMl-+gQo}8-R((uB)@xFPVdGCGPVe&d8`+dJF_6v8Y z7(ti;t(Ut?DN@Cg!{6jKqarJM2h@|KZ&CH|-s0}1jk^n>FC1ZEC!N5P%3ot5h=Is_ zJ1P2lDAly)mg*?sE&+WkT>; zmK3K6+1!&HVJaK2?Uxy*f9b3vA;8r1EL}oN!jTy1v@{B6opD}K8*`~pbn+o_!nKcd z<Qk2@){v-lc2%j4EOi8-sg=%9 z+G#~}st9oq2W^vv60Ci)!3=L{$6}kQpm#eym3{z$$%33%lAt1zRgJg3Q!afDsF#k8U$EfZ^f zN9v}uKj6Zw-@t@~lyr)=G0C= z=0>fsFU_Or)sxpMK9qpTq|P|HXdXi|Hi^oy)s&aW?j6p)9h@*|iP zHZ{|AB8C9poxAu4V|2IFVmFsST1Ln6#Ct0?jKGc1SMB(L8NkUKASU<{8MRGVxR2i^ z*iyRhQs)3t?6}3B$%)$!gcF^w*gw^nkd%^T)b6UB6m`#Dy#MT~JNyewsHJfKH%xrI zLg%G47bsdEp5q5XvrtQZzOMtp#$v6n$Wy^7NWs3)2K25h=T}6u;|D02lV^kn=NDy& zR-Y||&-|?m_1O#f*QjMB=e=Wuq2REWXC4um5_X?H&UasTYRXucHq_*VBTNa`WQNO; z@?VS(SJKpiDkXn&pCS=iEY)ZY6@x0-$j-@f)A|qM5GC)p%OScarO>ggI8r(`qQpjR zb_&$wV-8sGr6n$%O|@oE>)LkvBkuh57Rg5j`qcdZ4DbYzIUNpoo?#WC!Uz^iGy(JE z$NU0r7eRkz#kl=}?8)OImVvKl6nWOU0x@pE7JimsIks3?z_`aX|NGjI>7ZV$qUS0M zPSr8JB5t-gCIw3tpyv76&7C2J%}Sv{n)BIj{JagoHaB;9J$`f<2GZVokKUmJ35Vz# zFKS(dvSrBS(26USn{}k#S1QB*PZTj zL0W}Hv469BPu}fLvHYTg)(K71=3B;fb9>kw&;vepgPtvYbN`B;9r=OLmbE>3k}K>Y zWrt06aGWQFjrN4@RQ?hrYzPhUc15Tp7+#Wzs$>{0xVmH7Mqc+u{d)#^E1p&d@77bK z0~Nl*YGA$Urimks>c(jCZ&(@f9Yq)DD@qqh+fpKku%XMJs3DP>L%6a-;cU)Zf+Elr z`JrJM%K_SSK`n+PXrDntsHBhK0JJxjfyY!!@~}tD7K+=9r^d*=$6o=_yz65mq!UsYk1qd zNBUVlC^Pa5`-IE9fKUB5uSVKuxLWZpSlSb7rOgxFjvp{9dFDCs6m6!gcYMU|6xB^SeQ7X1(E@*^Gh}u7TCt^e zUNU@j?t2dLidu9dNoi+PzniLPXbmZAaaFZDQ~sKTOm^(ELm8inlj)g-OmGCY8|+7n z>PCK;&w#<-1_DDgfM9X#&H}RZ7ZChe`j>jTf^qnU`O71Ls8Hd{?2t$xt*&5~y4u*1 zzCS;Nedmg*dW&fM+Wr2@I9G*ozK2;$CNT@QCnZl>AbpQbwr^5G^VYcMLf!RGn-@kk zD*jlFaXQ&=8MW8qw1R2G{8XtJSa#0LN5llRroFCH_u*us0oW;xyWbUObG*!irmrdk z(@%0GSv3WbAi#b$`ntDxQyY9U1df$3Ce#rjze&+G@xYb5}CPEuhlwZJK<`1O_ zKswwJjU6^q|CG$49jhVk$H2%!?KHu>vG^d3Fv&L+p!MG#`^bQq7W?7Z@ka0o*CLn@ zxe6RP=y#wG8qac5d+Wwcj@NPG2{4AK-k5_B<-MjsObgSa^vbVx)4oI3xeEoe^}AB} zH|PJ`uejJoSa->Hg}?sGkJkUfPmC9Q8|y!GF`*^ukReY~PGyS4TbQ}@#*~(Nh38_` zFLkZ_XL9PmvcC@2MZzym>CfmCyF*i~1BxSzrgPi&B2F@D_^Q;m5-ZacPrm*qZ$I1|9bx`Ibe&Ulr$M{ryJOq7ZQHhO+w9o3ZQIU2w$n++wvEZm znR7AUI&=Hh&AX~rt*UySz4tFwl465eSXy)ai;vb|k3T=3I}P9;n%m)L*vP*n-jgJXTm?le_Jz$ZNecVPXh|v#!MR#{<$E zWg-P%?p8eZ%Q^2MMY>VJT}ff-$cYowwN}&t%1v!jtK}g0m}v%aqtLSJo8uZQ!!O~a z)%qkhjh~)RziNv?S&zsXJx4QFSuUpLm}Xh{nT3ONBxT!3?qK8-hhQ|77spb=frUMraI3en z);+2sGE6Xudu5_DGVI0})%)g8BqL1dZ9}AVd-WbiuF5TBs0z+Nex#%(Zqjnliy}r| zk-F+~5nlwjzB5+0dtU589_-Mr zw}%g9^nLB8Wca6KPD>LKY9&QPa&dWa(3_-eJvKMlsm3d&Aq{JxM2!BPtM{PYOO1-2 zex$d?FhOa^#j@5~vm>cRM~+dmg|U!YgKodd0Yv4Jn@s?B8f1=9gn@+3DjHShId z67Toi<-fvZtkM>xm@vi+PhT574JoxAQmtkcD~c@Vw8&?V>r4nLdW4Q_qGtYwvHsyd zo62eq@-Z+?=9LddTMp|(6W#9r8s3Si?J*NwC$UG6uK+ndhTF6D(OQ1g_3j;&2_p|? zY%IrW6bo-S&yMbYG9xAS+4G0f6q$X2TUHU@{x+@6D)w>>Qw6(O0aw<=1-<+<3xF|b z-YRch&i8v(71d7*fL+)2JT0DEfZ!XsM2e%8u$XU_uP*~SU)svwD^Du7knQM!mDEA* zDDa9>G2|U;4>xhHX%S@i$Ob`0r2b^~lyO^lvuD;X-lN^qM&@Tat^t!)k*KqJYzEct zl%4Jq$i&pB}9??U*gO|MoKKg_RQvHIYeHUd^X5*FTp zq=<`IR0M=ctGp*PVo)@5C`MQj3@j16k+5rmo6^kQCw5p+c3F0g1uc@S2P~_DnKe*n z8d!JBQylQh)^D&JN`W}KzpGGm7F(cbj8&my?FUsY|2pByrU;B!GB=22CSJ&fEFc5g zW4(GN{a(SQCoK&5TU%?W^J55GQR{pEz@~h~-8%bKPWg+^`-?X;`2}EZ_bo_&6Y_P{ zN5?Gou+Q-&T5PEF<3|1@bn~=FPxCYxH`m!pcmJsYwc#G|^qwZIKDRzkK9n66$+YNd zs{7MbyGIbB%WvR5?i42Blhakv#60j>3)I;`n}1A|nTnWax4#?V?-lk;0(C--+E20K z%rnE2v*VwMX)`G4B4oTh)o62skv*fAXCAtEkql}!F920`BmISAQXfo{8xYb|?}%3` zK8;6Kfc)>FIN^`w(|dIr(T}W-Zmw-^`H%BM8FCEK^&tVHK3Lm?i}i8u+}FxX4fNnz zA7X7!WH}A=n(smy^Iy~sbPvfb)kOD{1DcMc_qNnZJMKZ8G>=WpK|idG7ys+uJd@nV zoM!K@jnLLyzw{?(q`X^5T3Y*4{v1CG#y z`htFreKBMu=lJ|Hor{(RNk8~bhj!@}0au2KONXr2Y|5qEE2l15M!hSlw`6$ou<0_s z9V&%0)l?aPjxo#GcuRzJixjnMy7J(8cMsKhLj}FZ+Iy`>&W^5eYF|&WWpdjM*f_Ff zx`)H`Oe4L;o80kj^h}`f6M)BGI3vE|JGxfFOiPOjamY}^WLg!CqA?vTIVEiR`VV7J zL@lUy|4%3U>E~Q0{~y)o|L>Xp-vwh;+n<8*PfNUUoGeRPT3Axnvmrz&sTV=9SjZ{` zO@W2dBHzBSUea!{ChOnS71)IQF8U3sIZFxC{>!@Kh<|Zz7xn_nfMnlh+HvlC_HnlN z%vIj^#}oG->U!4VhWuS+ow$A8O$mZHQPe!ka0AJq;}@dPET<+Kc{QZ=kPWByqCIIy z|B}7hP(w+^=sM#Uu^CWUa)qV(NbiNCUYuUl+nh+GA&E~%T@P-z77`i7Tbof+4$ZaY zyt9r{^Yo6uT`$j2kMVNN&Q%wXq2=6tK;Y$)Q?3JVRq94nR!2;yCeL7oK2hXJp&{lL zk}yY-uCapJ1yuqpI*fER+qvm3&)g&#;dr3#{50!7#)Dp1s;yYT2|75J!^AQZSr5Qg zeqx4=zsBlYzcCo|-czSRdorevx)|P8RZ=c=Pz)wft}Mfl3t7D7nTgIF&QRrH(tgRJCdGoud6bk)=LP+Y0wVUVx@-B`}4su#&Y zGI3q5mikEs&UzNf$AUQTLtP=v88_XkwNe&Vo5{zh1Um<5o~~1lH|Gv>3@)vj2Q{x0 zBc6Y{_`jX`x|W0bYOtvWPQM*H7c}`v&=2?;in`il70ZkYbh#E)<-%HfsY~WvC}kOo zbWLF@h^LoTeaHQh1xe+rjArlq;1hq4XGK5rY4Nb0k9J)P7kVq>FYF@4Qpt`rSST`$ zUzPBep8kEj3Ap@cM`!0OfLC-MDQd=SrXOsWyO*Zdpe00&i5 zkz|ogU=qO~#+NY{iMiN4)!q@*VzK#DCzVdsIyO}$A7ObuR z8n^pQ_IuCvJ@0XD#^-xqU-xeV)Gq{KC~;#CAYxYw03#y~`cRV5i(>SUGUEpZ|NN~B zjH^c}9zS5#CA%EZ#E9WR7kYdf7>jOfF)Yoc7fTph)UrmP)=OmPM`ubKyUGo zeaS@{Iv@NHXk|CLJ$*?989RKqt^Zn>z0}SDBr+=$Mu3mqOH?DnkAB-jaZ5y$Q_CXhCmt zhmI7Rc#V(1HoSR9XJBhp71DSOj^CI=gk3BiaG`Q@EUz1M<$11Jz@1Cg9bP;{0sF3t zw_Ls=)+7Qfjo@O98MV=;ovBp>oUnw~Fs@s~~6xMuodBPrKqcx0-(z6Q}=!fft38m3{FX5Wa;b9->pw2Q*=+OL5C zFj{+K#$*raa~IF6bhB*1dvfR$V**Oo~T)A zb`MIOu5UIe0c@y4=~~#G+Ais$tGopwwbe+^(@N_kOyh+uaoUFIoqmk>ZQ+@*O@V)T zv|=P#j1ONFPSq5QoeQ7Q301h=$FK^*a?sPv{9AJDueZc{Y7FDdMV1ncJ3^wx{psbw zh@4fG@R@ASxosY!P*%acY~AmMh*%HnLjX=Z8&0RCCYYuthHd7YrD^UULh%~-g2=(n zCPt2CYHcjGbIQE#^)pe1?*>SL=%%+gRE0?_&gQG<;D7y_!e$Y6Dl_4N0+ zyiH7(FsD}wqS<*Wu#Wr1k`J2Y;`f#y(b>YSJ< zpH^Dmm0niI>VjumSRfIk* zpViU^_Er@bLqB7>nK$_Amx*`3HZn+2pn*u?aPgyEtu882aSDXx8qu;}dvjEMHRb8{ zkY*>`Zj2t)cnBQBsB$IZGBbn5`u`ACX%KB&*D#Bd9M& z)PZz{*4lD=6zLK%A#ymJD^tXlYa!z-oUD*tttw$zt7)Y=cl0vCqUk9Ij@J{{)f@S3 z4;hiv3AMqxyl&tMIg{z_vQLbW8#fPCR@UH&1S>IZoNyvhA}J=XjBVoAMS&}R<_(7E zntY4@*xd7CU0yC((?4-|X|Y?3Z4`t&u&$3Z@$#$;>exRi}Mn z^V3Doet(IEBN0FUBzx)SizZuum#GBVYid`9;$~-<5F%G*lf}xtv#-v#vwNaCFRUVN zd!stH)kd?o$mV+j-Mig$ePh`vI)FjWAP@McQS}-ef}q9jsrt8$x$9I5jCsRK2d_#o zYFFMI_ErnS_H#D}quEQ91M#5h=gxslw0+++d~YANp`|4agV-7SsU=sLLvzC$D4!0c z2N7TJYo4VUUkuT>fdf0ds_yP$KzV?PI|ll@(;I-KS!4`5+P#x}g_qs1^Uyl82~6J) zUyKr(nf}q8Cd!?7>kiAn%Kw}8;-bLUqu}M$_>e4>1_xmONzN>U^Cue`GT{ls7Zq=3 z6Qb^m4itVy%?oE{SZjCDefSzFi3$}V{6_UML1ARf>AwVzdXiYjgWPCo%yIgs*jQ!S zMfHgulQOJLB)zX`_k|PWkt_QK+FPV&LfALlua^)=b6)`}C@R4>YINY8MCumL>^Sne zj+VR;K#+XfdLUXp-$3G?H=JWU)@d}N!5Ve>b-F9hHF9$~B zLu8sKAvJ<`H}8XAb5T@M3^(2wclKUxiqA^QO1UR8Iml5>yu%9S8Hv<0!@h}a(Vyir zn^S6Ge~bIf)-`~cd(wn*f!jLkzJ9f}AK{zFdj_0)<(zyWeDucCz-LtBJB8KtC+$^z zheRym4zh>8WYqlQ<|{jI)tInhR2r2fcCKa8?zNSmLiKQcUp zpPLHy|M*lFH%DX`cXA31k8hAy(9a$wHMDzes5hMQgH5AU7o4 zn6t1;{PUT=K(cRx_Q87}f@U=So}Ij`uFQ0CcYLZZ0uzJndTKV}4FI_c=x?^NLGf0!X_j=0(~QeCRtFMm zLv#|mR8^>Tg|BeMxNQ{UjM-06d$O4-)4W_qvJQ2cniZS!Yl*O?0f!%s)Ly%kfQo7* zTqvEjM1EgMKd5DAsEf{Dpj2H3+i@(nN=`ECko`>5(ZhKwCtF74IJd6W7E`LelU7C9 zv?(Uv3^f}CWfs#;Nq3rD4!M^b#zRP!Fx)OgsU4ZJH`ITvilv_MHj-5~wOXoC!!v(d ziD4}{*#vd0$lG?3lP2AO+3#P96;U8E!8?dTO#*dfE0I(Lp{LD|m5hbK&jlh)ax$~n zuQe)5=Dn_eG9qx%9T>yCxzrMt9MO(lvPU`L{`wPYc*=t~>W^ZqKrGg*bFHLU36GNT zLGCHz=IsW=&Kf$jZa^+12SIi)bll5xXnA-J;!^9ANBa+FZkR^ zzmlc93ii3~`*8XB7#8_S?^nk4%E~-C^5ppTZdS8jt)Pk{MsIyKq?$d*y3!Hsrx)^@ zhpcBie#&0*5YJLYr<&kkU4MvypQz2_i)zp0+)-KG@@z~xh?$hs;;`%YwqbC$8{@uu zcjM|<8$luoYo(;*70QO6>ILD_pR(?S1vr0Vm!8!+Wp`ZU7=rsPo10=NrZ=EZ-FE-A zy>RoWrk7xJ`+UDvNY&9|@W;?qmjHGP|E9>S_LgyY@E9O_*Ws#`ecW&HZe`qCEApKj zk}d3SaQjNo>t^(e%fA0;W?VWwfffAF(4>BfAOEujK-t*I(!u4weD|)38&bfG2)w5~ z8;=WC%U)G)D%9;S)euB4Dk#+`+axuHF&Ad0?5OCPDk z`}dc){dlc7CJkyLVCQ5@_iJOuNdu5|K(!xy&!EC3u9Mdt=2&{#qe`#uFd;Wor+_;- z<^#Cm#J70De`{9^Cb31?zQJ)U8R=Lk(lOnu z{1{@j@2FHsqoAMbOIJvugK24?%}emZS#RWWoIH%!S)yoXL+myxQ|tTn{|aYnJLYK0 zeik?2hggRHKOPnT2kQLas6pyWaG@nq6&Z$KQu-^T;W3wnq!$jBR0(hW z=Y{QG>}C9^O(V0k#{vCqVFdiwFMpKV89EZOP|2rUZu9HW4)-se?>ATj_#TMo`jJ~2 zq2Oa2dJa9OYUl1fkLg=75$<8Ip^sjs30#ILSMO1n0YkP_m?&Y>gJUDM#8-93h2iE< zO{#~6v6Q~;_<$^`$zP#I;>IR^IW)D&K_hlqBcm_{rDZ4%!Z*qlr7uWXl;P zYw`=SO^)Gm$g(sHOFd8yVW1kP(u%D*20+Q!IC}r=~KzhhoFL=U2~}pk28iC zsb5L6^-khEw3^YQFq8lM$v&94k}9wtdJWOPrauZ&yl#V^$Gb#oOtv2V10S_p@YA_Z z+XA7^P^Z)p)cUC{JlYGVu+YZc<_I>#{=l9s3P!m#M$)a!6W7Jz+U(M{-sWHExeX)X zA%bbpRq>2SMaWakHp!3k71I}n*>=0C1_SPjUUfWvm zHh|QjYJx|#i(TD@tyV4jnrGFT5A&_(%eHO5SF{&(|8C=6&wI0@>8yR*ue(KG_+R}p zoCCo0yYhCMIgo7-J767%n-X>l?UKi2LD=Z*c6Ll1w+=~wm?K1D5w#v_;$)y0HgKY8H?kR0riTte*Cv&uDNXN(z z4TlKs*z9*uRpYRbW4^SCw?VJQFb6A4?PEB=2r}-hopX>h)hj=AiSn!h9hPqXB!Ek; z?rlp1d48&h_@Bn)o0TD6nWspVg|S1II1RG6r$MU5)yS(|Ltub-7l3gSfAVI3bI&8! zyWw0kUS zi>G!UYccp804}hcf$0ppTjn;7N!l5+iQ{%a2hFo5o+Dpf)~swydp{|iOH>~7ZPex- zI*k49IDoEU3s}8D&0n&oJvd9>v52qDBvKks_iv9Wu3blG7fF2~^ac6a3zc2n*%_97 z)yWx`ebw0+n4R6p8JV5k*%_L>Z}&)T<=mF1Gbf9?eZ7A=XX@2nch4O!JR+*SBPwKT zZ2F(wtv9^mJviTAS-OS{&5b=Y?N@{=!^r2G-~Wd4t__WZd30wM538fn#W$&29h-9c zwnnGn_<$Ei@jLAIrmxL~w@#4YJ$5{ilF|52Mi!YP-h}OL>!o@2km5RrjUoQzFNX*P z1f1#llOTl?n6Rt2s4TCpF1a@^H@CJBd7R5X)IH6fJcfChHH(1<7UT*eim8MNCzSJ} z=pJ3;!n8MF5{~MuDJ-@YTPjv*^Vo%`t*W=Qt{}LO&$AS`#?;uV#w`EX*M1@hM@mPq z+Fp`U@fObx38bb>TEV=9zD{-oei0v#vU|sJ1Fs)EEBZ`)g?Oao(7j8X{Zs zKsnnesY`)%0tv&Q?u%Om3`{+QsFj4QkBkmBu(&#Zjeqm}1m=Y}0_Z~)ZgGv`wyHWi z+t9Y+%FH@DuT&?9zB)gF3F{2vZTT{wA7970f_1AU^#!cr&Tna~rcR9yI<&Lzz@KJ= z5Q{g51u9NPhISsZMn&7h4zLE$1%JwPNODJpWs158OlDSA{XNUXis*O}YYpG)jUAI5 z@H--%Q$^Rpy?PK2+EsA%U_c>-#zH0knZc4$tAyTYH?qfCEQpsb6g;36LYe3yy2_uw zv#_(&Qfn(O1+>=Z*A-3TKeEFItAlp|0o$q(g*XC5X=nb;;zp~Lz(C0{))$`@@Tm9S z{mW%qonx~tdW-4;CoAsSywu#%#^Od(RcU`r>gkK?Lb9u@1!N*eXu63Ac+2eFGV?!{ z{KCsU)`+g=!!X3IZVotF4g>cxtLL3poZG{klm(gqYUz#b&-@AyAQ8$G9=kk0ffi8@ z>Cyu337E0)_~XXufG@#DLaUUl+lh%BaOX=fC)UIvY!f#u`iH%3s}anfpKwYplw*_T zxJxW_OEz?&oDM!in`I5%0xO!T#;q3W$*lzrtf*Rbo3Fmg0d*ZQa$A6+Qow|ivLVF= z5pM+vzj^+^5Sx>Uud$A}`%Xm3rY0{%det`2HI7S7HwiUh#pKcT0SO==LCHvtgaPs9 zoi-mV*U=Mug^ib>w}_eh`61n)PkfMNS5Q*gQfjIxE3OQ^-uE}tmYAWQYmP;LO}_Xf zH43#lFSLG4BHpWRHl)8Z9Ts za@4}Q)|gkog#$(gdQ)5^KdHTeak$6WAL#Cr&@AkJEf!VP@N!a`7SMgV4fNd5%JBrIVd78ReP3d*+F5V^4TG{$s3vaDOPd4brL0d~z-N*i z0@;u1Hf0-~8Rk`+Lx>d&2(V!2-_?jB#+u1&k;=HjGf^k6v6pYKy_O4)Scr8=BKqf&%3B>cCbf|6 zdMc35&(n|YJaQN6^{)~g&dt4wAovp}oJKO8J9lP|A$KJH@(hh>Dkb*HG4whOXIlA) z?aD&KJe-4Y1I_m={K9?iK<(+dY5Y#pyA+NW9Qe$=*7@_vUy2z%V8|~k+mnF_t(b9k}nrk%4+S=C*lY=Ij>i8kiMCEe0=SGdrwn~Xx$`Ilw5aNi+xrWjb?DO2!b!(LM z+?AUhfif-#r*Fqu=A1N3jewMoO7xQ_eKRQeGAHKDvVDhcX`ZTqw5e}% z7|J0_y4&o~n&vnUDV{pR-)L4IKySKx_E>ntdJYk~nI4KC|48)~h9_Ur$@B&`#z)sw zt0L4L%R+nB$|6>W&#~x6rDVGa^$5J(C0J5Qz)WT-K&aSMXj}Eg~x|g=PkZBF-JO2A(2v; z%dYu*sQ6=r($E@jRM57HcaCRU+CKB~z z0U7pFP7zCbv>%1$oi1+xku24vmdrlgC}p)s`w=xcw-h#ji!m{ zp2{NYN7S+2#=NYM_AU-T@9~2StY^Li4DdIWLMa^qGGFRmBC>TLKg)JSjoQcr3qx1; zVNv){qiMnnfC^0PJ5#~Pfhw9 zXzeja7 zODNtlInru(4DU1Il3<)_XzeBiWKnAwy7LO1M#vZP7SPxDmliW9KJW*Z9yBsr^n9A1_s~ClY)N=nHf7)5fkJ5g!ZRs&Q zAw3~U)@hC&iTuVYTOAqEVZAE8;6|q7KbJQ;oJ8ZV8~U{md6?oPzcpO;dt$bgt4~th zIj$WjPO~OLM*6X4N`)#Xjd0&3pQVAVJ6;Yd9b<)Cb`#?X51+O6 zvm292R`Z0Gn<^hIWuI=|DCJnA7IV=y7`BpLBs17;&dfe>E|(j*^vRRgxN83SZCBOJ3%ubRb|tUt5?XcANv@vFjMID-VxNDn*lL zINM(@K1=pDAHVDX3IboO6JUSe*VCI9-@u8Jo8FbEmTF-i+gDiER=2Z1=(^?YdEu@n zm6bLhhjUm^QbpN^%8_4uX_r4s9z00YXqaCWyyC`sPj{Sz*K~?6O9cAd3cet3aDia3IB){CpMD2OCv#TKo^9+;) zujmGv{WLcB%^ajZQ^OvIthmtMaOjXrA%&EYbzE9#7#MRo=FrEcps}o^zC?E7+ehOeT&|^)7-mTe&w2e@tHU^3f{*peHg!eMI64l~w$GrddmVK_6>nvG$q!Oc~-w#@m zS%!TN1H5gz(-q@cIR3<)Jo#F9cJ$Gi*Rs=M>?MLK-UwmMd{6K~`r1;}~Y3 z4wmOKMVwesr~!-Xt1v^U4|X(eAP|{Gd0f;(ZF;ApFoRy6>|7U84|NFuIm{rDFRR-9 z-Bt~0D*wp?L->+IB8YP*z>@(9F3hK#Y|JPfMtT4|#sypJWRj^oq^RI`Y!DmA@7Mr2 ztF8j@K!iX&jN)(kFy&nw4q&>%CnXN}+R%GP|H9f+u7QlRVg&ep&CXr}FyCGK)5GWf zWLYw0OsMv)Mvi|vJ_IvtXtV080riuP61tQJN}B-* zFxr8PXKmqy3)TBl93f|ly=0FcJhP(9wvv>JqGg_lQm0Q5-s<#eAex` zvE7;GO*gG)gqi}BW;BfEN}QJSR_c?uSSYRV<&izl5hHq9xedwH&`#L+2GEI%WV|+o zyUgVB1y>}>X}Sevl7&S|kxJ6-Q6gG56v@As>xUEzNap{fxQXkKiS3IGif8675o4oe znwalmiHW5fa_cXmqAsKO9W|=E2Ed3G!ezk{%&J%bG%?K*_n?yZrcjod>n(c;M|3db ztU0#OzSgXoHLM!AqSdL_!8BJ!I~yXtih=hwJ39}+?G#fn!T-=8#YiRR#F{r`A+=y3 znI?TV@&i9AWg#Lh?IO(~37KRGnH)1@Awr{BLO3G7XyZn~J;Fb1upViLT@U4c@*lw# z+lF9*y|&%f@CyozxTi$g!Jf(neoIK3u_FC_nYeVw|6@(4FY7^Alih<0m*}t*`cIye zgRXcVnC2I{BL`HJ0hefvupb6 z#e+RQ^&&S~9P?7^rb1R2ydO_UcM!5pc~CzSQ?_Msf>YELPw5qp2hXTi)D;HP#F8$! zFZb_HxK^$$vnmeilA2l)q8vve52A)cqL*nD#`BChxAdU+>K92z0RF-Wam{SWg*Ue) z!d|Ce$c5dO+k%9Vq_ofYhZtAN&~YhhF)75XEWHH#P3fIP887>gdVE2-vpHd(_0Uz9 zPnL|RT)`5I16{G=aC+dq0UjP4_1LJJ0cv&-^e&eU2)j{D;&AB?~IN8T)QH{@wkZzwUFfoB!Yc# znVlk$YcN#SEk(oCSU_u7!D?D!g-ka>euyCD%C{`Wjwz=qQLO_)6AqW%*LBf~&lb8?&&atAgwCJ`fka#d@g`y{s%~jX!AC|5j>xx>oOu0R z+dV~?%(ni7CA%UG%%GK#3EMe0*yvKONF1B@mUz`&UA6IZs_t$VPF1yFtzBKgq@uO~ z#>z}9wR~epmuw(USA-OOA8BKUj~0g7!Ht2W90sAVociAjJ$^ZNQmx)ViXmdOH6k-N z_F;-Y>4tcKd}^@YxNTW(r|V!<z)Q%}uD851bI%%S zUUAIRyy3&MD3DwGFgfc@53J_In-Z_F&p1S*_d|(+CMB38=F`*R)&r_Lce#^;O=vUJ z4uBSiSh<&v4xdFj0@D)YIukrl%*bPCpDk!hb6;L#kWre z>yQUJTipb;9lMwTdbSI{grR#pb=`|*sY{N0H~jn}y*^|y%EN_t)_dud=nQcUi?qz< zV`STv;;dVGMpjIdM#h(v48r`dLaH6xgD<->3{UWbeJ~0DcL9vQv?oBf{ujH_ojbcJ ztp6XoO&DuOYMp3d2iOqU2h)@M0@~^4~+AzBh{+=Ucn2< z%1&PW?{68-H+_m`KGBNx#kH8(J9ru@L zd+uGRi&PN2%DOBT=WxP{ba$`;c~Yv&nmEWis-9H6u48&R5mg@<6&+((xsI3$)38X8 zRA+n2!ucfR5!!iy(tysMDe{vA4w*T!=}g_GQ=s5F0B`=L+|Cn3FF-xp|AQtmbbj38vQXx zsX*FAXfVS5>zoMTL6lKC>4;zsMSz_mlzGIsLqU3BaF%@GOyR)`S&B?r`VUkh8jv;K zOhU@II1S?6QxNRK5rTB2Ey0NQ5%Vfi4^ph8x{KD%ICCaDO!XRVjatRN0dLQR5{`*R zioREKCW?H^<^;pFEFZnE-v(?)nAlhGe7gIr_Cr7)xZF$v?+SW9WL)e2oM&uL@?My* z@A%e*xw<y`J-;AH=|XU_WDB>M z(j9~g8&;=-lkPE4Am1DMJ911RLYE7b2a*~QvP6m2>n!y{7NW@^MG+FE_FERt7}cEb zu|t7L7KBjwcMrWzn~v3Xqcwi4prrNk6?zaL(>-n2BN6Qp;dMsIltJ6OUaD#(kmgPh zGvWRT!2*_zpj}2*MDk?_Il&Gq@xmT28CLG;I^DR&y+1eYOgX(-?M2X9`(MY}-i&%}%caXKuY87~+S{xF!H;~- z2_FPe?a|$vCGy)7d((GLb=(Lf_H_pW9i{9bswdIa2Ix4_dH`H^kl8akcl7^Uk@A78 zd;PW>x{RFsgr#H7*YRXLy5o~lob!Nc?&ek<+0LPX|Fg$V#bX}1q14U&Iqv}fyblbg z-nn4cgN;-75ENU=KhXP9n_T*hfau9l>&+O`e!$*z?nE{v%}rx2bW7z&>mP^|4tqAg zfg2PiA3k(HrDzCLG#AN8`a91k#2d+>(hZMsw*=C|5(bZTR}|7C0hJEf!Lo#(^>>~X zU{<1^x%y=t(xWvcFA=1BSjt=rh;Le|jN>)vr@Q31$EysN1eP%c`~sEmgokX}9o z8aZBi>VO57UE!uRbH-m@205Fc3L|bDI=6nsJwJ#j@Lix=h)oi_AaB6_O|%El7P9<+ z-7QWmqW=))9;gnD+it?1C`@G94b3f-97*7wvj z!={j_#&Gmzc{P)vhyCJ(<7UPFc%AD#67FFyHvzA0(KTdkI{vnVVn>uxPVL5H#Wi7j zi6DFT1=N|FP{3fJVMwE3WsfcxNgRPEd&Z)WucV=oq+tk?)Fe_|?7rlV2i0DQ2TqyF zD5dO9@()R9Gozn!!7&nvLlkvFfR;mPGyxJvvmknTa8?D^+zQCtDuhV~ItK=qoH!s! zu^@U)h+KPgTyCe_GEs+=OHLA~tXK%M&9u&vYo-}wrWwlgB(*2fHG2<4&M}0^3pz(9 z@PI7VOhTV2S%XQXz%C%fCNnlEwO_JIfqgFmL@pp!IliB=T%nD)*EQ2q^u~iDGW2@! z@#Rn9u6R5tUn#|nJq1eMpvNtz4AQnx#|xZUkC#ZP`fC$Pv$2Sigd|4wt1#n36q;014Z5;jm(!v3Mxf(yDIEfH zgQ87*?E@bjLikbS1E7mURStqG#}=L7a}(HHYU^8}4ve~F=^HK0ur>uo_cEPGY*XGX za_pPm>)~;eWIjr4`%QNeK0y<`Z6?%yL>o8G>#^J8rYd82qM{d03DoN0^LG}CG;xSY z2MtD*JaSX1qfx>pVHyPT2vH^aG%3^osCCNNBwa{#Lax1p7%};sypub5r2BFO`U4J0 z(-(bM^;?2z&U>3Q@RIpQe8pQ3lTzH|)_{fQ9EGzgg(HT>#BRZN)_75U-3MA(rjg;u z9ERROa|4wVj9!qDli`8$0{y3eWWuo&Lk!w?!&ICpnU{F47G#Z=FlCqhL5$$&MDAM75@q)s*WHX)f<)IG;?kV`=LMrgbxfoYUYZ8|d2(*ZiHgO!?pGRu}2mKW4kS z>)j8(LsI(kbYI&N?(E4A?bnL#+&QWI`%osfB_{g3=_mZ>Z^={U-IO;DEUf(HUy~** zxam;}N*-sKs`~h{@!t?4mexce#=Ol!U z8R5wpGS*@B>GXuwanEbnm$f8W@FoPVV4o;AZw>onu&tP&h!Rt%W?ogz`Tq=lP+R-} z4Q%-aNjL{z))U1)e)vheg@=o1_VX{75MR*SoM0ls+lyb4bMB`;p}Z@Aow_I7JW|43 zX~N*Q4dE8}Z-@8Z-dVFPaN?KW0emd%k{E(8Gg5{iU1Jb>GKL`doVJe*4a?#nZ^N5b zlpPLwx#HTq9l(XuKF@>7Gu*vGX%DKCv7Se|smvO}kyEHo=Tv+p@`%wmBmA>~ZGB^i5%MBlxYmO<$2g z9-&D23kALzlPBa2LO+(46evx0RXre239zN6+om&)@ZnXIPFg#iaT6Vmw-e0Y@V<@1 z^?~2E<d%qQE1oC7(gZr>&!MN|*5TJc{G)6injD%73x-%h~qWVOQTtwD)$0Y9Z|#rLCRA?Gti;__qab$XseDev)@er-tFV9F>a!1t z$RgCU!4=2?mMI8h|PfHKsJlkp=oFAAX_l zE`6Zh@dOlO!yz&=#wWb~hv(-shICQpM?T~CBcH+fA0<*Mrq2IY{nq0J>4Bnp=b`GF zm?6Uz3`2+jfp8U{@rNKEga-%&;-Ehmn=#Zx0*ovy12XU&a;vSDytA{)h{pjP9t@!y zRb3t6?8-nac6L|>=hr(Rd7*TbbhyV$q&P4Fwa3}5Gl ztT#KhZfARO*Um@Pt4{J7f1&$oko`vXw1;$>&vMIcm;0smVJqn!V6U)YS|M&tr7S7WIKPlrR7k?3QFa+IM#+KeKfocz3*)eC zflgWkvV=)7D~6IwGHbST%481VvH(D-D}u4nsAN;pEEjNg^NDrmWRP)OlA+b2hRepa z%sg3fFN>A7=%I5;7h%YA_lh%Ua6bklO{d~{%sDMvA#7rkCO~I(2-#;PQSX!}WmA$W zLl%6{Z3>M|ipA!ZC+IL80+P_UEE1B?CYO-NXyUC*Myv&9ZoRrAx3{whQTndv`IxKi|4)V7n5ad#iP%ITPl}pCsk60|_(#)z^%q5xx zGh-IADW^3TvT3I|7qY3lbC2`yb#E|q3FtxPIu-Pw4ru5TkBr#(Iz><}kT|cTMQYQ= zhD(0RS1g?pmrmfHTaxM=r&8$MW8|}u?kPdFZUa>=F;n_gIj#QRe)CDPaGf)PtK28> z5IsS?aQ?mq33bFL_SU)@e8|6#iA-iJtYJgXw1uP2fOC46Ox?FU*VmhB*MoL)HQB0M z3;}_ipob}@%h2dcsw;PqP9Wmay7i0rcZ3J3&8{pl(6507E2WO-T0r}$%^+5$R#ZY- z(z@2Z(7+wkYO8fM_~_;4>3)w6tLDgD6*3UI-%sEGmG2Z7zcM1Ina76nu zkaSr6m!)+jl7lC^g2KT^H=u`FTOsif|9k1FrK3D6=T9=u}(`9uG8suw)+JGhHu|Kvv4Wnb88HPKSZY-ZtE0MKM*=mu08MXoV#+7FN$u*q++{!6wj_>tiXVP6a~K zR+_gB+@2apmv77!zf<&g^p{oBt~|k4oVGqDEomHoPX2i5d0e19g`}>t6)G5ZW5J|1 z?SPEOnEvtc3SJO7)WFxwKz%OdyaWs~?evVd+x>VjEy0fBh-D%*_Zjje9lTAtCuMGv zFhfO8;>r5|KwBs9S5e-aMe2&@u2-?mdE+x=@j)B0>Un2vOB-CA!C(6&$kz3R&yptI zm2%r7KQWCRSVeWZqu`2%#zwELMKQOMK1F#uZAj`u`9Qtm#J=+L*h-sQTIh;D0v9VO zX_SZuqYH@Dlc@j;RAQhJRTJCMhXNK}1K`G0uGjFPwaQAY6v7njvD|@3{=FePXDJ?7 zN}7^%k)qql!ltk7tBP;GUMMGBHSN|7ryay)%V*$S1vG7hF?T*;k#Q^L(P2#;9hH{J ze5>7jjE!N*j48pV<11Ub_&=Dtvhq%R=#DxJ3OkYqO{MXxUgH9A)ejF$9K708Tp%3V zUVsY7#SRg@&Ok#*ayXQ*q(BhG$vJyOV;OqLI?W~r)=1I(N)Je?affv=aX`@Gr*ccC z=|1R$7E_ZcALJU2n~bZ+B?B#VjSnF?mf9joQUqTm>J8V?Q=L*(7Xn3;?CcS) zmqe++weaUA?Z_36FnUELLaZGJw9deC+&Rq@;@|1Ph&uQ}`QR&RtAUotUP z!2J^_7LhG)ucv_xx$c&_i$9X2wTgXd!0hQ^T~#;qVCrMs#v?4m)LIcS>Xn^=zj|~O zsZS-OaRUG1W5Pa?o8C?;Wqoaoby|VFQO}ZzY0kPqF-$=hPFhA4;xy*aP|~1|-OFhf zsxWGJ(vUI9B8^Ptf-UlH!_dLYl{1yMX{JwT5VpA5!e~7Nk3aZU9k@VB*hH18X;mJR zMrm)}f5(&=GWQYN`eI?CdYDS2FEM_bq2h!>Qao zt%4(7F+W#}B=yVo#3j5i@?ZrEjDS%kL3bi1zNmQ^0N<9Q3OxfR@eb0K*DWQVX}vdX>ATCx*4E@oLmPt;_&WoG8A_rSjD(#pT4Id#xM;U&w zh*)D^sWI)V7|?IBd+3pj>Gc4%DdQBG4Qk7?=1~9N^j%h4+&tLcO&`jlmuA0t)Z5pX zK%MZMgXB2|%ecJ<;XaZ0mk#z8z2ONs&lR|Lf`go2L3)=Da4dU+81S5%2$?D8FI+o^gxoHhLja5S;Ms*ked&lhqJFE6kjA6F>-uBP z&RpjV+_oiMc+PS1e`=#E2KMt^FiIIAlKFU+PbC(f>Ki>f2cKJl84!s!WTz#NXJz|B2aU>7H zSG`2?R4yL}MG&`y0>4?blmzmrac$I>MO(IX@32e3C#KL8GA1K)cK8m4r*K$Q(6_(> z@5ycklbW}3!F9c8S;soJ#KP@5Zumvp=p`h7sY)I|*t6sSjiI2#jba7=ZgY&53i9~k)><6&%MNc&SjmCr-_=v)eup4s?77snQC%{n^VJjfXOPdJ z6_p+CQ)hSI091sFz*X{cal71~Bt4|O-`i&Hk~@?zQ8>lb2{%1d9HP_V^7ae-IlH6M z9Uy8vRILy2xu_A{BDc)Wz~4*v!u*h{bAO%xmC5!fRPX#WwbRT}!@Sb*%US5I<{Rh?zh` zB{XbxMS?>Wy$vj*=XZHd0`L8Fa>Z-QUh|3m_rqSVv9Z(eh<{t7E0uL@UrEtZ)BH-~ zSc$yYMNrEN(J8+Z;y9uvtx7f4QXM-{urj*pE4_h*du?q+v;}EZYI~D)Cq6~1Zbhd; zoT$^lGIfjB(Lm=8U_5r6 zK{)zKt6Qthlz!{F%uF|8liVh#q{!gNE3PA6ZHa~d*;q}2UWpD+G2R{#ejb=w86aw? z8F7#3*-l~7Q?{s^G}q*jO9rC|=UOGBurCnTQPLayxz!J!eNf~vO^Yp&0wcxxGm7)2 z2eHmPH+CBJ9QP9?)aw$fo4jQMyI+AQF-FW=7ue+c-YVi}829Sml`OEVouSjqWb>Ji4jWMAkiO#P5-!Na|09=nFG0`4>OlPSZ^oMV zpx?K)^@_ypuTmYW!R|25kL-pI79`lzNL};WiTqt$gRdeG~#r^Ck8W^ zsS-8XQT$_{Q;FrAgykBA`GrhuiS@8}U?_$MZ zekXvjG341XEdHaG3TYE;*NVtKRiSvZHmp@9BsX5#djYMj<$QLFCujyT7gRrIQ&Z86 z<;&o=OxHEPOt1H_=nF6u;G`yTZ%f3_bO&) z|5_nE4>U@BGj9Vdf-8XqUiDu>aKtvb4&%z|@W)dKP4xTImnR<|#$)RQYz^EXkEU@U zC;qy4(1(>a*%+{ybwmCcR}YwGY!3efdl>OXTlF34vLyRBS6AY{;#hFDH3go2)`}Zu zsSmU-q%1KxXgoHU&~8Inf_LcGL0^nOyP$`m?eYc0Z9jnc|e#d>^>$`r3eR*=8-z_!oA>Y0&J+}~v zo#OwL3o9wa?(;|es7}2r2g*=gE-x7KW;HvN_5S#=6P_h;w`F|1kXd{X*nsZ1n_vg^L`$GE0D9mWqa1MBJNC?RjwSo* zfU~uaC-&e!0qP&mhpzPP9XY^MjF`*@kbP)^0+^%rBnG74e+Ml%QK1XKcom^X7$M*T ztS}K^+?}~(1C9)-SqEe-0+^?bWPgp?)pMAEmgiMeuf!-=r#YM%lswhr4e-w>K+u=rIL#&$C?q<@iG5IjSQnw+ zg)8PUK5i%xPd*{6NC!%&;g*4W^0SWQNo(Mi^f{=Sjm22MXn70XAZb*L)X%tmBc5>W z#C+7l?A+;hkw`ee5FOGl%D3nhql)ip6n~npNavgpZ9|{#Rw0(GXS@kioY8O4zZBD< zBEob(_@wnwrVT7D*5eSx!Cy>J{6$;OfN;*S#2guW>U*~SO_2w)u`G=dND`!^n%k{}Ry!i=&Zgys%|8Mp8yJ4QpSlkz zbZDb`|Eyj(&pe|Jr?EkDgoNCR`8Z&AG<~x{a>)N*YC&{|eNB%S=H!&He8d_=>#;l3 zckc5+Bz>0 z6J?_)%Gk7iI@*94DN@FcEHLsYFk-K>jv-_vDZ(>4*^}CDxmkAVu%l$KOkQ3+!oTFp z$H>`M^!$sng><=?w7YY(0O`R)R(ZGd`fcZoc4@jTymrvhKkMNVe<8O3MN&3@Dd9x} z0T#4u3wX8wnzX+uuApO>zRvd~ut$RqEVUSk`_xyiwWjPeIU`O@C@PL4Djq2n-7nvArm?2-RWsQ%ei+gE zlf5a>_AI+@>-Ig?MS1p%YsTG)^J^%tg@0s#%`>}}M-)7xyD7e$ z`S+doMR4eLHmhcNSe6~^grjRoF$K(`^KikAcx6z6$i zS4r89Ov0EwWTaL3;QoG*5v*xs&v?&x%(!LGc_SF_OW=UwCk3ctjtu@&Wl{`CAqTaV z10Q8B8KUO(3jR7+L>NMi@{N#%e5=rQSI2kc{TN*LGxdBoWW-<^YWK&Ap<>4$)#8md z#OGJxRW)=WzRGQdgO5t0Dh)!>m8$mQ$1j>+(bTTwSb#GLdJJ88aYPs@uCQNUZlUCC)FVMAub*+o8#f7BL1op5I&lVv^E=_f#2St&zS80l`IVL*q8|&=d_!a;<8F8R&Z%W>4|E%&l;ZTr^k- zjXMtLQyJF{?ZgQ(%SRU}cj~3&Nbioy-am%8NBa^}WGnaE_nP*~8&liTY-)BUZW2y8 z%7!NHB`Mu27m#WrJci(dEsW7TEJ*mFjftoVdeWF?QY>5X5^G-^yxL-dO5a@RO}qwu zhy54v0|_MvvnEY6#@S6+b2=j*qU8LkEFCH9{S>S~&<#jF)5_qo2TAcf!TgN)8WHQk zQpQQ@@D_rfm;r<2GRZUDQhr8CW}{J!p<=(YM3bw!BL1*_m_+=6oBLHiqB?4om20y3 zJY2gMCD?0Av6`eVqp;adkz&P@Yd~y&>J~sy9e*3lH4LGo7qP3Ia(g>>$=|k^N{kKN z2kY6O{ybp3p|HGB4&Pc1&)(9M2CW0W5*zNi4>?M_>DZ|ZlM+3R(o!zC4wb^bgNe2f zLtTQyQ-Cdm|M+WuK29U#F~>pnV=*D2?$$0raWmt%B_Tc-8fCn~}kwhVY$<)#Mt5kryz7A6MqxAp?s z{Y?}#uTtrXE~4JBJw_8wA6V%A3GPK*a{|6`Vk&I@IH^yj*gy9q=UyStdowXp$K=gK zz;f+Ln;foq?U92cC~Us~nIv4qSkbaPM+IBvu4{k%g?F*cUwJycR7NgefVM_6{-oY7hH`o7M>$$Ik58MT^ z-sw5P+=fiNfu!$=MvReE{yKa*(_2@CTXc@xI45nXa)QjoL2ZnVGfc|q8Bi&8QKbwF zs)USfOSO(|N?~TU8ZAd)NxV}!yC+ZxdCfKhL1UR6cw0-aWp!PLT#IqiV>6SZTz2qVHnk-rV_M;UJCoS=7g zlZ?BW#au#lo|pU((E)LoVku29!RX>C!3b?3f63-!e8oQ};bY&F192?8M-GrI!ZCHu zadzwX#Cq;jpoSm1RXlFRx;$=3!lShb)T(<=X3VyVc0gB7Bo-3-6%Dnhf@EweRmlNc zc2bhLHd>71(30*k}x$y>u{`xM!<1#B)I+lVrYELv0otMXJE5}+)Y@kt9f zqfVD|?_2X}y(>@`GfIoeNTM^Flu?%JNGm=m=>YYp7=@pkkU64*4(wKCvCFfznMgQe zY(SNn8$OISkeZV*rmFT{^(H!Hf1lXeT&1}M|Jus57>|FIu6Xv4zwG^Q5 zOp#EZeEDG3LJp-QZd8Wgh{^PXrg|1>d8QPU>>g`*J_ENrVav$WDNpB-+G5tWbpPr! z;BNCX_WOV}pPXxKbC31e)O#^ysORuRIz61K&ZrY4>4gUNhLay$J23JFtsQIIN8g6{ zyWdrhvKMB459$sj5Nv->avhfE@aq*Tc9@}q`yD&&$ju$xcaG^Dq8sEpXzgh3mGlcE zZ%qHrWjpS+Vd&i-Qh*Fjpp5nFmM~|rB3*|ygZbQIvY2Z*>Qu=dT9Mr)F-yJ(mpkm= z;@ff@eMx{b%gNFWYxv8e0bIGDOwmE6d{Hw9c1=tn)20peVybe3y2Mcnq1^oHQo$y9 zW;vf=Qp=b{NlfQYXrH9`IurPSEkO3WI{($$af7x1kYM zs{_7G_zXuItng`7TvD&;J-68Wsx7JHS=LMC>1$tlW)*oI>>=D9FVJi_`x`VX*TmMY z3>s`2j+GhGJcg}Ir8A+l-Pm;jsM>%Hl!W{$-m2iZHKziETNhGSGiLhYiA z1P&edNcrO4%}{!Bfj$#4pFF`nJEC*%?Hu-qtw#!n$CXDORvHHuS#*^%CA#Op|C$8> zdTT$k_yF2)i@M~NLu6X25aJcsCUz{Vz2^7cT^;i-@gZ)SFmjP@nJ_t0=z2BidX`1) zBRUBwCLX^lY4jQaYoM@pA((2Gl7Ua|U%y$d4kP9~L(Wm`rtQfUL9u6pK{YR=$ z3`%I%MOLpNr$zE?>0&MEGBA#abc4uR(M}dr>PvrgM8}Nc)%USf!_JiX^n_^~Vc7OR zo1qB`$hReCUhTDl_7tNU=NQj8h%kdCDwL=%$!C-%`0859!ofxh0UTrP^)-1SF!*8H_}cO!u(U;Fh4` zCGc9UtbiyU396K@)#cC7)Sohc4UBZ{+f{&$+J<>i^NKIJ*74rL46%EJ4%O@C@(eos zcq)V*_<8`KhwMD~5knzP-V`y#?~e|G)&8Y}sc~P`|1NLp2suco{bbmhyqW0NS-i+! z0v|7kiB~Wmgye?lc4n6?cG8@i4asoESDpXm0ILg0F)!voq-(Wvlie>iVOt5S4}4Ue z_-=Id40VmUmrbi*r7=p9a^C-lVjq@D)Tx=~cjJ*MMC5Rl z^kkpC2^ZF_Y8a;2it+aI9h1naz(wv$!;7tUlCm?c!hv6E%YgBwUWulDvOGYYtas<% zn;h)f=MmT53@3r)phv<#KB!5A6*--ynfGMe(}r7ohe_iqN9~v8RnBRICMrH7CupwK zv#$3JQMrEYJ@?&QgWVU>1KTzak5B(+t})*=7DfOM@r~T;z|+9E(YCz~_u;=?k} z1use8reI-piy9f9Lg$c!izAXFzI6hA*N z_iV>3%c{GrbN4ELE*9Qg^U*{^?AiK3Q_<0eEB{jU?jhx{(YrJq_pJ0sH5(v0mgff7 zL~N{S+1>Z4zcL@eO&>f)@8I#92exp{0J#S$r8zF>W9yn_H-zRQ&jF(cL18}Z4*e6R zw@868iGR%Z=~rwKgCo07h|3dPuH>GWeWF8;#~pUyX_N$4>sf1k;q3{j$*tMZ$|K{pu4TCt1B1YeU~b@Ht%l|FW7f2bv?VW?LMHhuKqGB#t2Qo2^1V-r@$1gima5o3m4NiMq<7r3lE zD)|^rhfT!KL?YvcQo2o@vi8>Qk~`^*_?1gTgNdW_gi+n1F^<-Z|3V>S=GrSEZipi` z<1A(LQq|K|YX~hUISq8uiCQOqK!mUKkJ(3jmq0_~_jJGm#(2IyQPj&2(CWYd_Mk&d zzT}cYcPdCyvub)l$$*Vq7&RRVx>b)sMd~j(E%xe#?fHV|fM+fE?84^|m}Z@J(JKfI z%g+ONI)txkIRBkZL3homFp3tTyKHt$z2(q;9xdSRI=B#p7Q?$1cHG`Iaf3*9(nM={s>->fK7YA)aOuhcH)Ez-sI$MT_!B7CWB)ve~{sbH;0` zdT5?i(;bX0yKmjhfPV8IVOx4r%g6FKbs^AZY3xe11<9JstJ62X!T)eu~>mCtgWEeE4VkO6Y}=Hro% z@s(d8UHf8H58e??BnrjX&V9HQeEJ@g*psT~tEnQTuC&M2V?q_`_Fdbpd&9eCzNlHT zUej|b3R(orxrc5Ox#p-9acN`=acO>W-|iU%Qa<`@0(!lzC|^SJE#JD&8_XO4n55P5 z+I0x5P3rR^wgJr=tWwLW1Ie0^mknmn??{D;xgWU8TxytB9v$Cn^V`NB@wT6@%)NM2 z)HJded&xP6SYe1crDnons{&FF|9>-8&!1<%(N^<@dLka87Vh2GSay>V_kHknr(00; z>wSfIH1Xi)I`sQ6cH6a;BEJ+ZfsB2X4*Z~a(0=hFU&a+QKYjmC`0YD^xtzEk0#)n} zejD$9IfbLcT1gKz#%CJ%y2V9KA;&c%}G)dgh{_BDYPSSkK6P%suPL{&{Am`trVk4e(<_ zV9{xd?=pVDtR+$!DADCnGz2pwz9Q>am~IS5M%1Ou2;*WTN*b&TKXa0&yvpJ3X=x6* zk=vzHLJy<@I5#xhx|@!JbE-oX=G9uRF0P7B9qnO0%jw`3Q^`Vm zHm~^V^$U;HujJPsCJfH}S`7NDoQtGmQu`R{x~TV9#zefNes5upq{q0}taHZ6p=h)B zjv=s1w_6^j#xUDut+zT#1h_dW?Ca!tHbi`iFO9}c8XuD~;0RFh-dCEEyV_hIng`sk z@iydAW_ckT`;JS{`B`#Fb7a!xE~Ec(dv->6=#}SblIOF8PPePqvaTGPVSp4FE0OLd zl{&IvUt7Tu?g4C)16;|oiq?&H+3qivD1WR|z;GTIRqJ%@Gi>yG8!BP#B^RSqDBJcv zmI<9k)(%yvx!cqfR?}1ar>(DCAC8h}j`*^VD6~Jth?aRB@y@8`bR7sXeZlX8g~99{ zVk{X0plV&Wfb0+HVsgf|@Xnxvu(ny8niP;cqL;5>G?!R-MeV;aXvAm?(jCPmiEE7I z+dl8$cUOv;+XW+qWs;JKwLJ5blR4xMK#4C$``qyldwHC|ME03lsbHaSiOB2uy}(rV zHL4ZEVLl>;M{nx^ydn>oOoqib9VFRG4$?@ZjIsvDXpA}hJchht|JwX=1r}VCk13GO zxW$o=#*s59K21{#hmE$4sa(?orO%-)XIN^YWXJPQOuffdl2i1CV9i{FyV8fqasc#K zUr0+iYYilL?{O{#$pB^-4QJrGhi?=*pGaJ{s7x?Fi>8L*zW2rA(%D{bZsuC|{RpT2PCLuqXBVjGqq;}*IgZD#yNv0Svg7$8 zu9Em8bT07(kPbCa1 zXp3Vy3%-$%$(I+i-kKU5Q|dchYj2;%66(92gXa$DXDa7&Pi-WmDF1$sHSFlUkOkMl z?J)kOi-u5NLL3(ejV41K={{cnfnY}!;aPNugwH}+p$)8YCpyCJT22xLZAKX?VS91x z!^eFJ-mrpk9q-Z`AwT|%nMz-y@zs|?#OG2LPy$2U$GrB1(8>lYi-hOcO)udxI08e& z>x4SaclG?$u}U;BTfCMYCb=B4C1SJWU%C0^<)vz6k8e3GQohJDv8Xmlq)t1j2V_#g z^ptA!gy9&{O_q5x&n@3NZ<7Wq6k=kaLhjU#1a0GAWrhwV81dU8!polGS4 zg03!7VNE20);2-z0O95sV@5W}9NvptkX12F@ZX~_{`S=x<|hgv{_j!9{GVjB6ct13 zB}G)ex|$j6rdDzpQK$WT380;lB{`vSpL98k7;{1Gl@VK!>v_+AEy zf}`H&WMyOTx6KG2tEOI#fTO8#n14KW-n3rWTHyG`GyVa;LAh&jC11IiR=oVJo25R3mBAyD)d!mAkEjbeetm0V#%0vPJgq{Xl*BKa)r`s zSWKp!O!`RsadaNR0)1*7*b;r9IFv#%JG9dYmb^(L3M;+@0YPtQ8BRJ|1!y&=9LL{{ zXei6%8My}V3Mi{5tWMLFt}vRaC~^mFN-|)(Qkba@Y3yUsUen-BEVQhjXy>-4Fn<3N zLs6GF$g%b(H39iaP5v(j8q0r%l8>6U8?pxKSLhZZCJHGL(oAD(3G{Iw`Knd85_Xcb z%v~V)t`Tnwa9E=(2N6fsmeC;CQf*X^#BmpEzhf=lOT9bLI$hH9b{-@)VDg|p#gm}TvXy0mR zUMurrkz2C8#uQ<>o(j(IScQ~xN#-PdURTThQhaAs7HWxvoook5o+Q@5P=!Mjq+!wN zIVAH6(Z1GCfN#A2>IEOBf@o)DcSAA5Yox`cDM26Qi$;B{)&qE4BQIL4K)RP>I@6F# zb!TzAR4uKcBtKdk8aZ8^F@owBOFP|BY+zUUczfACf2-*=rMrI^H2y(D@C4}k=9KjT z))BRP;H~LL{yvrKgrc@f7PP9W=`!ka15FV3+`K^@o|@ppqhDlO2ui#Hclm zY0C(1>5K5qZB>BqlSww{rUKr|d5_kR>7+S66BIXn`*N)-Se5xwQ7l3<8-F_WlH!#M z6ie80a5qn;_QqfJpRu%!Nt+|suuI3-cuwzzbPE^%?`to3J%T)}?0wtBE*jqVH-Us4 zFBmGGZ}i@4g1hfis@!AjLSjxo1xK~+PcXB4sNrDlAO$Zw$`_GR8@Jjh|KJ({B-(d| zU&sM(^uox#LWcZE=fW?BWa+TJg0FDQ6Z?CRb-{grEOz->+})=(>l3`%nHl&=F6%geX03*C3CmdB?I%A7H0CfS#$Mf@Y)=NC5IwHfy31#>TaS@%;DFQ?Iarh>P z$$XD_XJ;R$z&*7FndP0vkn1sf^s^V0Ev^Or`^6!7QD@NlleWD5y!8L)^hMs@#8mN* zy|Jm2ll`Cn!sEvFKo1Hc2Ah9QSjzT~j&2gO;~QC4Kn9i*ZjK#8PLff$-JfmHdIJ$i zPm9qE(3!a!o*L)Xy@U26@{0r&h#64S5F5f4pwK4Ezq+8_YnFId7%>5EApzn!E~I7< zRFJ!>C0iea5My`9%NTT>6+eJhW;J@EJ z87b-y(t_GoXB_sue|OzJ_S|N^&V#}TND6;>rwMsokOj3aPJw^oe0IUsfeCr3g|1Pb zmpyd~2^4WqpPxOI!rEUv!NmAl#!K~8=Ibx{oj>Jaf2IksJ>lf|RxSA9uqu`Ip{&~D zJb8JR1%3(MVn5-3Dw*9*4MH$`>0;uprBhpwH_hT-8`h2T$9#g%l%~1B?@wgHb_!8A z%^L*KP_G|LV^y-&u3nTvTODHOwv)cE_gpD#ajTkM1u%uvMX3QoMsT!4m` z7P$h25p0J|qD{;h0s)K`OQgb6!b~W#HYs=X{-pT~KB>TAKbbExzI` z`CIb-Frf)=WQ8LRv%ZkEovmnB7q}fJiuHxL6gAe)qaV}#yziq%2*e}7zg0eY`-je7JoscIWd3z0N`aszS>ppc{Vhs4NJJRcDSo2E> zs+T@_jyNyaqI6lpp$^~4W~8@+?Z8X~K$SLaZvScJo1yfZfI-ur}isJNvTQI)zov54`82Bwt+fNiU}%LjI!Ed;lFIqeqI`E+;{YDm;|lw>cx?wy((K;= zwes+rNnBUJ?3w6*$I)K?)ncHn*y`*6%low~{KR{7XalZa^s>sJr4|&I@vT(gZsWl0 zb8#0~xF)&E9IMY-dsd<=bQW)fXN90-tt^W43&w3@Z}4ia?B-6x@uX}UwTs9G!j?RJ z6CFL0W@kl5H2+P7&-g>5p$zSkZJfd7-cK9Wwqjb^l44KoTIx(iHx^5>qex8;Jz>gN zwaOu5n`Hi1qZPc9(*=9IZ0ktliy04uxnZU@K(PbXI!90^B`j2n0*}t4@;Jy~m*> zwd5F2qhf3}Lj$3l&?7!&9^N+?bCA9*`^A)V&}bg>8%VF>QTjv|SFK}OM0U&Au^oWv zg2{7RR3lJp^-f79I080EcBDy;l!7$ea)_ggDsPg^^ML*qyx z%NyzlygP$8d1X5|G9ydjfI`l%E1arZ=0P-jTKJ7l@zI5krPIT@hMF z6JM$naP4ZRJ9pl-^vu+XlvM3hWq*|uaW{M}1(YEJyAgi*R^IqCB~Ts9o97p^kt^nx z+J*CCtk4$D`ES(y1$`v4!fa@$M*L(*n33D_EDd1gLGpr=A2#|xBhIOJ{F3N z@ygV-LdsG%?ga4Rv&lVud?_;{%8swHx*|tmz83rb#1m-?m|YFF${qIP&R~L~YUlE2 zpoY|%(f1LIJz$~k+*JG0p!7b(@YssRKD1j+LcJQ~tgNw@1rk(>CNOP5Ab75o+D{OI zH_H5*3d_K-@>l|SdFxFYv4jCW`uHFU1bwd|>^<~d;7AU)}IMGIYF!_dc) z0ciL=%t;Y=4!CTrgJnDE<=9fd*bTMx7iBvPzr1BQqVJiEQwO7cPTrCFiIB9aMGWir zh;ACRrQoZbBFDS`KAIee@;_jqP4`Cp11iA{_$>;8GBL&!tSN!;H-^f6o14XtZIa-+rDmi4M)w=r5pp| z^+%AETW%iqSiAU*WG|&{x|V|)?^o%eo73=JuG)1330{ub&y4PSw3(SIeh=9Ax-~3~ zHM}%NR1l}_MncYxQvg*+!HyD6D26@_qp8W|4kt< zs`an{yJ$(iGEWPwf_DSaGJ7ES>Fh5#!w)9~lv;U?+=+^t&M%TTf`Z(U08(tYMwS3U z<&ex;3MV0X`$Yc|;v*+PHSSE2vxfSDM>Zr<<6GSVUM*ODh?&7dG83fgkzCo`j8}YV ztlGqaj8_aLQasO;SuUA`t4xa8`k_R_D4B%t&wc;(X5kb>4ymbovO2`XC|eGEMP!4E z(SiO8n^HQaIs0^ps~HTj1|rxg-wkx%`2}iC}CxJTCYEf-oHYS>7$2NWOq*MHKQBu>Nf{~XY~;Z7%H#> zg$1}eycqDBYAMKXjwQBq1!K=p`Y2Z5;tTg0)BZDETu2DozNjm^DFS%Teyh|{`L@f{ zxy86eSOl$$j2a=DS6DS|q2DA(wfBYNZ`5Vyi9qGM|5D2e9!`F;HtNg|L zcR(LgRVaLZIm30W8Jr+?Thh=UiT}g?Wr^SYe&x>v)Jydbd^W-j9~uMhe>)4DvvW|ixTjPUB|8+V=95@P1u5 z3oN?%iqr#;8qo7F2zQn9W@M&qc2aP+^~x#4CwlflaV5eqqIm}}^uv>}l96S3LM z-I0_7=_zM5-aY1_l-VC*EOM3A>oBWKTP09%R6x-N&TeuWY?yuXD1_G`*6(e2#OkCw4ru()adIfO!=D zKDcK*#)3$9B=mT2(6)%gtMYtZzOgq6-(cH9kv9V0XwVaH-2^(mDDZtLH9D)R)%Cn!N?JbIZBH#az5Qpj2x93}4e3l(qxo9!=EK zGE5HwsqVcTbW=CzUkfDb@0vrc;@Tn2n&48XPJ}A*V+Hk($^xaNu3PwQhnF32`dR*u zqW1S2kYo00?u%^2@OXI8fR%l zu8e|o2<@z}$HBx!$~?g7uVh@?;;x~ZSOF|sYm$)?*-}dE4}7JYcww) zL%I>Gb5$cK*>r*Zy-^SeR+X_Vd;yo2Pl5NzmlF>Z?V((38PC6QX^h$clB1Rnf6<4p zeNB2=?@F;jFmv_>;N9OO+gIXt{_Vj8K{r2_ zd_?EF8v#Ij&C>;fdyTzwSb|yN#%$x@_-od8<8buc*8)X!sRkd#&q< zwkHh7hv4HQAHU4aQEY5u4*wX8V3hEb+^YlH9_6>nUmw0nKN93+L(&;SIZ===nScCt z4%FBaWkf^~kd|yz<>pIu-;dqDlgShNT!4$DTFRLthL&(`i z&fe*Ur;#L6&Wml4^_DkE)nM$!3540_d4z?js@h`RWz4KBM}ss6Q_O3@D?!AsgKv89 zid7H<7&*;n>0OBH*o?=gZ$;0DU%6s1rPdzT*XI1T+WsjP{C_>F|D!T9hjaAI`_s?> zhXMj3``=b(G;M7Z4gWZq{#QvVMg2;BOC0eFUEc(zMF$r}R0>5{$~Me^umnTIA{>;e z2GmZDa{h^UYA}2}F^+!3Bbs0Ad-02rZ-&dqzgI-Rq^v11*0CQRPQa|i>FqQtV~5S} z`~6HG2;Cr3(ok)fk{{zvQ54LY7{6eA#F&0n%w|8rpFxzgfofj{DTtRaqArp0fNIY! zVqH8V$eV5-2N*5%HPY@9KrKR=v|}2MUXwY>sJbX;J7ulP<|R>qU5rKdyVB^Ix^?z% z0rMsP1^kfeMB|l*hLcWHu030{_l(ssfp$z!sFJ#kL{l1;k=)ma;&gIsN?uBLLA?Ec z)Pj3)Eu3lkEZO;*d!smFn~)?~>plh*m# z{FCve^nU7|*wCb!S7|ZsCjf%j$G9ZhLz{yUm?q*c9mPqnN$BNwe5-aQFCk*(&zaHY$SBm-lOff-0KEgUQkogO2z1{rtjC}5q^;zSIn zwN4B4{@R43tyQoL9|GV*)K*_QWh-V8+q#-F9${-r5Ajd_PLi%^%W=QXUajxQZ5Ehb zNu@cKOHqWxh8Fg&H=wC`!M)9J_yck(a(*CERq4DA>`6XZTP%kbfYinLZ1NIa9;N@m z-aAFf7A;wzW!EX&wr$(CZCj^!%C>DAr)=A{ZNIwjcE9f1qwnAQ>@hM%eq?^+o_p=c zh!u0q`N9!l`s-!=XY7x*hi>`>$Gt17b2?y8H-B$w{H`OzF~8n7N}8@Z&xD+EB4_%x z1$M=;;Ub{NSuIMZIdHde|OKyE%yb zSzg%lov;4^7LQ$^ldURhMePRmgyjRX!#UbogFVD9L1F(p5>gYRo5J9R4g|GC#WdLb z>gpnj6%1-tj{w!su`;R@n}=i=0uUw+<~P~LZ{*AQLOil@bkPw;QPgbfqzj_N3$QIR zi5UaUFBha1Z%RfLr;MAIWoBOdN{GSfooGEQ9%|$Lhc5!3_@zC(P?S)a#;8_l!JQA& zb#dgqn%Iq$eKTPV_u$@7Ch_1P>X9(ktyi4uJD1WZ0}h9^(+M2BJJh(0{G5yRg(V9@ z_WhEaf&(e_ULo$A2oK!C>qPmB|MvwW6{>KGVO$oZ@a9MOr=u_}_lMf8AZ1#L0+0N19pPR#6k9NzvU|?WEV79JcvaVpXqF`MQ3y8;=1AB%oANjEZ&Z1x{ zusM|j^}?T-1Am=AcjEIW{yJO95EIlIT8V;9?MyuU9f+UHR~7|>HGEhxUj=M(06k7Y zB`Ik)IRbcubO)+(mXf9&r7K?mrZ6*(9jB9Arjwwd1+=UfnVgjyon91E1YHQEU*e;n zVrdJCit~^24+8{2*FeWe#Zdq4t%@HL<_|k!2;RW{-{yY*xLinFxB9`K%jEs>Py5ja z`gfPBWa8}npSjjWX511;0KSs-YzRCRZ$yWOJ(R40KuiFh=wi=DJHxypr=m>9aU~7OQo+)ZMr%0eijTv=dw9h+O3zkm%a%frr(P@NhJ4an z!V238sSct;H;;rH?X?f4buvFTee|0}xj70hK%LfowuH^~( zU#9`eTxI|mKM1V+#J`z-%Gruoo7kAx{)b3XaNM-)&kSU!dshzyMPXNe!JHeub;bS3 z*f5He5UdFYM3eE8~3zT|+~T-ZdTo?d(JC^=^+) zpu96BA@f?+pRjbQZE~zv;1o+N9fb0+Fl>`(vmnzBrioxMiR9>4RV>m4PgZ*D1{XA` zMEjNL%6W$FlQdk6u4Yz;vD1O@{Z%}!CdwBd*Eu@LiE$?r##@`uKwc8j7__;a#~i%= zcUyk;Q9DQ#%sQky?(Q!x-`3Q6{v=!Ytw&pkVF}FFdT_D_E$feE;wLpbl7(g6&e@>h zc+SZtJ-S>GeB=Y9{!-s5Nsx|s9uHgy`-^#B=^fr+7h6`F1 zMd^C34G>tbUL+eUUHmLFxErxBC4>t2n_8~^38w3di7vmtU4X6p>q7JW{(qABS4Y)z z7cXH=9SMABWG>{i%cZ?3D>|`8#_8J2$<_UFlVFYh-a|Vx{8A$u}UYhYV7^{ z9c(itPb5qz7o1HZUFImP)E^&G3O^)Xj2tU_aoI{~3#T+X?&03_o5GW|ccSpF13L`# zc3NABV=bhkM;rD&o*{Z2WnmUWK6hN5C+(UnF79cu=jp9l$KMh;c)F^&;IT$0JajK#D$q(TfCy?S`SfH+ zg;O^qQJRn`%}{SL7;Z->?8jCf4HzumYsdRI=-~eR6SxO71mTGYTNoYwjY%&BV;g-u zXjeJqqAyZt=gvDXCEY%Cfi^WDN802lxhC^o0DNCZguT-a-K1$e>5E0VPe4;x2eDns z#;OeWGf=jZWmOVL;qE1NE6S+P!Ham&WJ+M9!IiIBTimSO)5PC%pS?3n8%fqXt)fQ- z{;jI^Y!L12+6gkyWz)E8hg!V!G2{_15+W%20+zWVa5ASMB71^JA-g|>*6}OR zbn*16mOpnUC`fylFB1?5;tonpaud7LQAgJGg0E$xwg*V=s zd`LR-7iV<3kXsClcM^*Sjkca+WN%%O2JIFMz1Te|$0w1~dlHVn)Ovbx4RqtXRFqxe zH4>}KDBeQ7Y@mWT#Ww9(Kux0y7XJKhyk-#ACrma4evaM)_Oho$s3dh=-l{FK=g}0~ zQhmRZ(!wixTL2>b^;=BKjgH|o5r>5bcsbegl= zT$U%+fp|u{px+uihvrV#Y)*sw@)kjWiO`HE66w;NWvJ%OP!9+N(N;7~%jl@%HMHf{ zqM)rQ8=O9vnS6bjAx@$jboB36Ridc-i{nmEN*NA`spR$I*poO>{1Jp&NCHsa@js#! zQX94X+s9~FXo5fX2DmSx#?{Wm-R8dXpd7~2e~WjAnMk=Mrp!0$^w+siB}{4|0&}7; z#+(<=*D>-gp3onhAR&eHgC54m2{ zj+rj)QL3o-o^g@(YP7s_i?1x)2gw2Ax?bq2gGtg&Keg2jPjdKu3G&2a3OPn5U3Dtf zSPA?-L3Zhc!9;9cvSkq0qJ|&}6|~0k1+}Ycm*sEu4i{!u#C4rZO=O_6mr#GkOIHA% zxjO)B)tY!m`;8zN0|c3 zk}Nz$me+eApHay}oyONksaeEOwXhscCOypQnf?sip2WanA2ciqp?R`is_N)y-sFQrKEGlnt-^;b&l?vlB1f?qM-=2$lHlRTL(4< zOgz^5yjNdJaYM$&C2UP8B4>bsxbe+-|m^ ziYigspqD20vuKasHxUepIP+OQ+!FDp;&uq9a>s5?3c zf_2j2P4Dp=ib7@{XosW(%tl8Tk3RAz`vq^{blwp&;U{vI?d667=@AZz_$H+r$=GUUq$*s?)x(}c|6hnRgV=o3;| z+%R%dn7II56U^aClLd4f%WvaK26=M{s@JcRm}Too18EBPdqJSiiU;l65hg-ROK*P- zKU}&6u+1=QV|DzY8fN`PTO;jP##pH-7}BbW0KR_N0 zK({;7lO$QbShq(X?P_d{-)*I2_kVgL*O{2EO7QFuEFXC7P&);&ah;lA#XWmaT%jD{ zQ}E#L7h3^~SkoA;Q{$dMb8kqqT6afwo*ogpE;MxoN70-f^>B1e7?>e+gwQUAT2xxy zKHOjbEFO*c8CF~Dpz7@P4e1qE_@hsdiY$BV;tTX)o}z@so`IZV(PAEX$&TzNotMJp zlqnB|$N%p7`;YDM@D$MiRi z;Cy)`Bo|qUn-Ysso&qcEFz+&JC%*G=^#oGal4z=IP~-*M@eJw}D1pshZ}bZL&;pnlEUy>lO+Jc1@-vEt%P zR2m7`M!zipoYVLC!9dxGp3x5YO#wU_ zSRZ^??~j?HQ;hTT>*E*T4$L|r7$7UKHDqJen7ID&%Ykk2ktC*x631;@^JyEu-QE~? zo|R4N=`dxd^HRcN2?|v$R?^aWWVUl&NeFGFi>}9|HG%!haEUK8V}5xK(mI!ui6koA zKamW;`X`dXK<|?@KS$$k_;duVb zJfmC*kifO>^gm{O@}Q00)9MLbxe*e zsg@jwY*Q5>n?0*2v5VZpd&c0JXq2ug+h&gn3vgNAShl}2&xIt;B&@O3&h@yt+J#r* zL34lf&6DuK*{6J}D%?hwztpOA<{FBukh3y64&zb)kqY)- zgt;oA{=R#DHPX1b8U0G=ggezz%w7DGE$@Xmp2HCTDG4%O1mDOPj&0*I=Z#hIC-7`W zdr!&QB8TEXoo3e4(&KsledDp>%2lrHp`7)*mTnOV80F?zST%brNI7e*VIfgW>dX$~ zLpB=*Dx{g1>|7WgRy&?L7;!vOiV~8F1`?FdKGQ>HFB=2RQKXuzSBAqwXd_r7-Q*3V zSF7emDIBGLfNQX{6<&eaPLB4Sk7c|qjNtSzT3-;O^mi8gZm+KR5^+!sJ;Hah6f#;k z6WI+;-0RQ4)&1ft6eciMk@R%Q6G^i^hwZrmKQP>$=@2J9Tv)4neBFqXeIw zD5aMw)Y5wH+bcXW=87Q4qD!(5Lo zw*y<1cCs%+?PThPFK2UkZf9x6evRxWTK+&a$Mgc6c663AQpx*;)1b%apO(QT*z61w zF^_Phb!fCQiC61Q^ofL;eVTb-z@fn2SGG7Dso00P6o!wo-!9FKKMYzw5m#iYPT0b- zr%u*kb+Ak*81+oaaQf+?jUR(Zd*{V<)Wmd_W!wy6{R}rgsg)8{bdlAtWbva_TRvjiBHlWVb<0+oq4A2o{+bsv4%E+opxf{fg#Z zJF|U$8f3r-iG9>r)BQ}-ZRcg@+x^{d10c6oL4U@8E{GFi3={E*f&o70D?U_V$Va^& zx*}$boph^-4h0s-PWq%!hm972DGFkQ;2sy+Lx+m7Z(#1Oa}$rSpic;dLpI>3=#7a` zs2@&((@QKnS{r1lC@LC4LlBQClkp<~F(>V-@?277ys^aCoE9lp6#3%LiL%Y+w?$zf zlI`A|ohSKOPbnB;`L$45MM|QKf`qG@fUJNWm)&T=C2pA<>kL{7FCGu}8p$xr`4RP{CC6W5 z;c3rh$xQ-%XL0#|LQL=E&k}ZKB|xZY5?ItblOj4_owcMSLQzG;usHi=q)&!k0OqII zDRB{zrI%wXC*7>VEYV-{)VQ@%Pe)((tjT}RH?{6@nR^)Jt%y6c&BSIit8iJ(Ixp`R zc~L0s<~c7(ntM3|Dmh@8M8K=egjWWbHr7@oV=;ir{cfxASwN>;36+snylqpg#ehXz zqT_Ob!ki^Gm<*H$YbdTNY1}FcVx{m@6Erc%xtOXiO&`QPV}hY6!)$_U?^5lx$V3=V z46v|96X?#{sm$FPaK*5raL2kPcSpOXVE^-MlBsqBNK5_#k4N!>j%MPWzoX<`yyM|b zyAKVTazm1ZQU(=A$CG8f)(0hV!y1}_j}J2809geaQKEk<-wx=8Ix?+CGd==-=^Q=C zL2(qW{&$M!j43N@@;X8|eN`s3&@?l8pPRhcwRpXL;dDbrXG#755rR$|2xGUg?&L>( z+o=8ckl5O@l3Bjy!N5(pCOQUffHfzXDAStjvPTERcvlrIMMrLnL}4&Cxs`M*;+CVM zai%6s!mF>$Hs@xsWd#DZlKNowGbsIZY8(v~dpAL6xCO^sna2=O!egM2gUf7em4kI^ z%Hrq>R0~+Eb?EgG%liPJtT-b!UDI^e;tOMIoZQB;3;3Gan+ctC_}cNK0b)X*jiY`% z&I}<_0E>el1u0#`9c-}$p2Hh@Y&V0Pf~wOWWs1%^-f0w zV%?-cQ;=055QnJ#uR{(|`(Fx*(5aF*dgrxJ=V3K#w>1YBZC@nZ5x*qoQ_N!L5PIKm zQM{bKp5n1bUMmx4b|YSGTi!b_{mt>ux&zWv=`dH;2wGT&4>*)P=>MdG|Cs_WO#A+_ zw#e$o95tETDgW(;_SmOSWg&N!%YP<#kG&*`e$)J(&x>1?U=LcNS@6)Un_81>k3n?5 z?Iu6JThbfNPYc}?L_U15ekow*MUEK`R+CFhDkh}G)mO(qfd_pY2!n8dM^ne2{e91S zN87CJq**aJ>RY6wfrrJ|m#p0zVr?XKb+9#_jBPB0Ya)efCX{U~TcUp3U_IhAaZDoV zI~nQMFRf=*eO))@=kT4O^7ZHVdG>T+pR!_JbUf>1FK33O@d4X)#wcpv3~e|sd#ghN zlzcI8^TXq`Zmj4^LGL8wmZ%e22csK4V+M9ljS!`sV9z~`&5Q0*XBbzEtp{8`{ejk# zYuIcL^e_2a@a66kX&JBOP5RGlJPZ?e4PgJVP5ccl7J|~OCCAn2&WnO?=V6a`ZRJ`X z{C^IQkyVHf-_Zd8K-m7*6W0G|7}SOBZ2s9XG--NxYpXo+9h)*|1XS5y*`69!ZY0xFOTrUxYM0g+b_hC>HH zQMLw#e<{DcXTNVzOORUl`hDwnR`5XP|ZLXZ9;L#zqOPZ=3T@O06r!o+iPS~y6Jsoup+Xvx54V<*^` zNKmSu`SrSDaYy^Qq9cv;;+^K~@2qEjBXai@)Qk3B>d$9!LsGv}#M>1~$MypCxX^5Qhu7;DFfPHB0N0s9pYqdM}A zidPl?jOMd2zy=+oWin&~<~J%<@#>1V-RlOm+yR4Yb+`Ja~;FamD0r zhhVewF2a-HZO(%q0}lHoiC~j_HTeVEbXgK%4>MXn}GLtyZp-F!A%>Z8~BX1 zVRi?I7x@r0D);uI#e+YweRHeiJ+o5+%X?73oDh_b zH@lmv>RRF))S{C-CdHVKZhRjlQ15ZJ=))($5C3{u`YZ3R9^0$f-B(>~x515^^jBGo z-w+>~sGa07UHB`F@9IIz;ipuBpUGW~jIUV87RxK!-B;CUcfzw5uWyc@-3^|%GZvrO z9p2$5S;DvVou2VW4XL00-JiLSj8Q+fSG>88kpn->4>~-a&?tSYZ=x!+!&^Ir3qRrb z@3G@yQao1Vv~ZcC!hIbjl#%xqck&pCKQb!jlr?2Aq(QiXq|C#6Ixbwt zA!nS1n=a#q^?H2t6o5@@{HP3r_(1|loA&AW$SYTRu?5PWwe00ft(Wx+-NnJWZ)o1 zr7DCjAzm!?84s_=-`Y1q?_(QcrZCN*Ly{t%JO?GXwrufF6>IfK9R=MkgKQ373RA{k zOmj3i=2d2*n^POiV#`AG27QgKZYHS8pYnSoE7Ry$ljF^=WUI?jB1*4CY4yiNx8j(j zD{!a}^zMZwg>xB|nTus)Nv}Cr??_wY7mL-cyHk^%!9uR1irF$HY8Yu&mkHL1gCq=q zxzr~t$_u!=)Pi$y+7LTSfn^xf{*~&T#ET}4?=@$P{HzXLi3X=G#Wt?w?wB-#Gr2b8 z|1D&sa2+_*}_S>#aS*H}Qk3I|IlV~Dt7;AK1`Q*f5`jaq=6geDYl-_Ego*#+>8V9w%3(bkh zk0DJ4v!?7KE0Sn|Uh!8>AGz-n?e$Um@HZr*G)SVgq6wSISS1VH>PMHzA%nC>Y-kj39d8PM+Uw73lUoHk`8F!vZf0E?88+t6hpkMyk<0;)76G2WB7&9K;Mv9U` ze`;O-wRCE35F&EP9mZ1pYRSUyCRwbWOX6MPpwd~_p^>)Y#8|792wh_LQl_;XM~@@5 zivE_=84IZ+(186YXiVl663|#D4Df8C(4l}yher8yS7+^@ojH_@ad502Ikz|3tOCy{ zV!q$`BCf>0iyiw?f~2k-=OP(OR0=VAu?j})qWA)y99q8dpv-~QS!_*_oF;ZE0@eh> zGO-k4UpfH{MIXa()mNbp^*TC?s&v2_Fs=6>8evUaQo=Kgga0AO9svVMvCw35WOQw- z+MRkaLEK2wFS_C(wY0onG#>GnZb?#(ZyRm`A!OoxNW|#}VFWlHoB0}k1oSH8ryHZU zP8?H>DTrd*I{cji;~e6TCCL=DtHCnT{c0JGo-C9<$#@81EaR3em|EMLDvtfT3em>k z%^JLbk4>F2ci|toOydGE3x>&PPf~JG{~(!&VQ`RVXHju!S#o)7n3&cXdbVY$5sgb`IvCt2 zqk4uQ$+C?ZBW7#M0HvTJn6f!QFO#l+dp8ge6S{1P8a1w*9g__1p8j4>bCGGOq|~Ic z3VcPUfr`j__|p@L6^*CV(Hpqx#3M>_x#}Tm41$0awMvC4B)Mehf~#btdbunP9Eeu4 zt4O~EyKoiUP{E3q&mjCAP{JL4>tKO9b6-_ok*mGDl~uFI_3XPkve(FEj*&xJx>cFS z8A!wz&79n1!@a6bR=ZaT+=POm{RZXRm$0-{TP zQF3`g?Ld!XZ~ph(@T*OrP1|8=o@}#npr&c5s1%JF6-?8dV#NYQvSq#+{0Wi7Z8E2d z`FM!rLo%mK67a7W?PiT~jb36CAr;%&$G9`r;AaRjNR@_E>% zB}JR^O+~ZNXN}bbJw1a`mt;*kS*;;JDI0k#2lL6XI%?F2+|q`Hw1@N}*0KibCXKAk zm_o?4%lM=zh2t^v*s^+t1Cz)yx4fQ?V=hR}eRp!HHZ}R+U&xEtJ@`W{Va; zYDQu1;%s^ML85IzT#6Bt7N`#tw84XJMqXH+ent!$yrcf$*fq`!q#9O zA*FOGc_{*P34Ptm@@R!jDj^wZ$qDs-gu=Evrpj)-v)Gx4t+MK;*UjAq`tALx8XYyz*MI)MI8QY!W3F1@nZW-E85Zp4xD+#tT)=my(UciaTF zisQbco8UGh>VV=KeyXZDm3V^~WDRi`d1gNAHiD(R+Eb$;snO{O-Dp21?<$cV0=mK2 zjaxTA2tyG6#F#qvCwnxmK2l2d?9cCumJ086|D z(8Pd|!2(0*8v~AF?%nR#igkXCaZ^JD#CMK|j3NB89Q~uk9W{=k>I)=!@|S_#S3meE zs*0+I-%O?D0B=tdmX+z@b3I+Q&WF$4(M-~FCNup3$C#H^hOvdht=cPGeWL~h<10R@ zY-n*FqUK;|7oU()D)*}n%N6Xf1qH4dpz*FB0Qg7(7ZcEnjm@lvrzD0vDV#m&llGO_ z64z(ovA&e0%TV(HKtkLuW+NRjX$VXJ7I2~z;?W?7CQr$5y!_77(<$!f!!uGGZrh^C5gjl zHQ&qOOLum#)pzz%8K~gR1;##q7cpMgBf$yzOkD3P%83^0?NOpC-B#{QFBj%-^rVxp zpUvu;AE}_}I zUNCjo%eS94-Zldr{GJt0NNOs4vgPGR4wNe;WZvL%d>%KIeGTd1r6Hn9G&~X6P-d7s zV$(>cOK!c{F6UnA^0Uz98M&Tuy7?;T9%;G`sE4%nO!RN`Y-&8Bpx`6@jqUoU2kF4d zBhG9-d8T)Oca-JNAl%?1`qb`qjnc($ePU%N5_dKma)Z7VDWafIw)9040 zPj#vf1GQbK`|aEu{wmZ>A-os5To90hF-ebH^>E$@Rk#sVPs3# zCF&3fROO;aW(3M|UjBsCx%TwPX$ol?ALgblCHiiAZ-Xi$a@tZHy%Tk)H&>d+?8X7b zkZwZ#hq>7wGgRv%K2jTk{<>HU`kaDdY%5$UFvj|&N=SFOSqH$t=lRB05ssjF0j93f z6jSyfFAFi1p2}6Zq(_ljqg-;E5e*I}Q$tx9Iu#BjAdx@(<_n>vi@2#qiakj5#-=hV zJy_%cVy)L}k?40UHeGVh5pu|PTQT2lbo+?wrP$Mp%#cHT$xHGiO??!ye{PrO$`(TW zE*sOP@H1HDu?<=hrV6q2%ehXeJ%NbiW>@96IOt#79>k#L44~>HaJZALX$xqp3+eIX zsBFAT7S~v&N(rwJWpA zb4E2FCF*n=}fg{ zM`3y0ArAijS?qML*-b7#LribVIU}CQDRLapw2Yp6gSFG6gpRUI<7 z{{%I*T%fcF03`PO4)6Xc_t1htX+hzw>XKe*n!t~_3|P0E*kpu5C*yAVp3u0Z%()4x z-Cl5}`es3Bu5gfli(w17%`!JuoQ`9-L-JE2%tE)HKCr!U9ijN&;njA78!4R<4I}-& zJf&GSZPu3h7M3!pyo&5h!+1w~%ar+q`}%@4H|Q)|uM5A?hA?)69|(RSf}z?qbx$oVwKV}ZkHe4K~?^teWd6oFV3jI zR>lmG9oDae49BNlO}*ifeRM8}blu2n@ICB-30~n3z}#_x2~=T^_~u-jdA3sM6GQA6b_o@J~# zOW$P4$9MQDQQ^h~uV=;Fn59rj93c>H8}L$Iy}TEtM0J5xhJm9E^>Wk=-7Vk zKYphkrCSpcs8%FM9u2E~3&qqZveket=L-RUYU3yxvGg}ew_Ey&@4EPmnq8Q2r|pdP zr}OANaV0-!$#wbByC9x@Fj)Gi_~Y?b>FFD}iY8m- zz=KmA@M4U*f8G0V`XHb1GSu@Ac2+Y*3Ov#I$8};5aTyJ!)hR|&yb7!hwrVlx?dZn= zgNO78Wb_Cm-Gj25qp`!I&m8{wJEhF^?=^EzC``Nm`#hzlqx2^J#YCp6wMbUE1(ds5&JtN& zFBh;qh;>715b(O7@s>9ok=)rouQ_GvqCm#SIT`vF8Put1%ELu(;qk+48*LdM*TIwY zD83Xfciw3lCGE)qSHXu?VdgxFLK5wf;CpVQV>_ZpjY79w!1UOAG$8N0*FvzLAmulc z=y!Ph5%59>9+2f%h~VM%&20?*F@5VtL^bfucIcA~z;^~&G_$`NsN;=Dqx;NXBxSIH^Yk*#vw0?{W7{+;+K-Ss!>ifw0SlU zs1GKse0D1dnu|!32&Iv46Z?b(O@BfO29DkB-O`CFp$6MyB*_8M-%<~{na1kbag~`= z_;3Z!H?<#^2Cs4e-vuFudIMtj47SRhm#9iOJ`1bbuq_ur$5jpBB7REGYv2IWK$WmRJ`+2R9(xS(O{rmBh)%*<1H%L~@LXxjrL1b>4x!Mb2C= z7EFi2oD`eq=8Z&iIL8>O8 z6k$QCR)BejPZ3qX)(Y0_Ct%e#+{7Jm4wh-`eOFLlVDShNwi)*P;?_SueO&;3(>}8< zhPL||CV1@Qz|?b;AbqD16?jbINZF;#IBN1W&Hx%k_2D&B`cw$6m0KwHS|f~ysn+&U zZJXTs*VM@Wd##zby*h?BYU(`r)lB>73+vZRRNoHfw^?w`w^Q162KFlNwPP#C_%5{V zGR!;jZ!OKa5DvFlsx^p4>c0N(mQ1jj&$J$Q{-hSA0-T7eI!-FWUa zvgHBCh&Bv&#-I~HaG!z=cFu2AK=PqGZyrxT6+kl7+(*i+VQ2yjA`53n9;wVOxe}uy z66KzfKC7aQM4@?HUIZ?ZC|*aCy~-wJqhH$zjNWon_ErFFIUm2SNV61Q>Iy5c@>Xi1 zs~kTrtvVm<@puB3x{fTr3#zGnHk)>h4Eu*0ST9`OpQZewy&hp*Yk>DOs;8G;azO**sL*&5VvGauuDKQ`{HcDZFV==tFz_SUxC_#=nAo3@-v|e zusk@dC6z^w?3a^AZCYj%G6L$mtqEer+tIdb>@ zLvexnp|{u@I60XZ)7smb0lou+e1yr%iorr*{^Ju^32|Y?pLdvl1jG*;20+zC`xpQK z7}r8bNM1rn2>(Yb%GAQz1OUJtFj#r}A7X=FYbIH>yAhmb2#~zyakj=v&O({ZR%-2& znrEyn1mYRRHrnY!#FxIc;HwdKoP%z+;JmNkFsp%fUh%L)$ObQ!p@h;;gbmpl%raz3 zz-`YR+pkv~WXA`(xvvhI^T>2?$SO*5gMA+Z2guuZfV$X1R3GLt5h19Oq+?4l=7JK>h&^rZMv+UJb_X}8j1t*EC5lB0a zubeGXFHO=@G$;^Bu!;W~DpxaETO2_Hhov9QUp~mk*XA&HGc#%2?_bI%ft)i8K0Zl_ zKD2i(ug4{T@3ZihP%QcJe|0`TI))#5#NV7Z;zlh#XvK4?uCE_V78CUkxGC@fiwg!s zV;ht2#0kO}q#F&CzeuBE5K0!#SvV_u)Uz*fktZZyVvD(t>iuffMSaw&Z++T%&)y_i zj{b`hJlImOqHx*df7)J;l#b=+Vo+3IyUW&gn1N+e0S%$>6@FMJu4^(T7of20!g>^| zl=9&MJ4J8+h)|b+~Ffz4Og)sixftt4>TWNCWf@Ds5?%cSw zJN!{_2>msdK}a*Ji&!Qzoa1gy9-0iyE#UlUPn&KTJiB8;XZNiQqKej$D7p{rQN)|z zri-bISFgn`)SzU&Yu@<0fI;)TV?M4uzs@r;W}WPbC%PO7qrR@I&Q}$JsxjZlQnJBW z4gi?MMmFUhG~pT{2--WenkFo!!cZ+%jta^y4MsNwMxsW1m9~~E<`TGBX-VhELeGig zp3?pl>$CrymQ4jr7o%s^i54xF$>jjD)?1hQ9AzDkJGOX#}m z6{aGmI>3tG0db@-YE}tDRc~eV=JwsJHeYCZx(6i?ogA}=w8}(363>4Q5}loTCYZvYS=(~6lS0j;z2=QjdKh{y_83+e~_Yo4$f zo`jkB$q~ap@k6r#aI&)aA=LacQ49mK|6ii`zeMqWiQ@maL}C0NiNf0}a+ePn@^=_W zlYWsstYC60jbL)1mAhMJ9H0h}DU&!1F*vY2EIy#K%t^R_r8++dBmYv6HKR0aI4r$@ zH**MBDpRbDAS-|furz}-Aghc$>`AzTg<+wGG%$efKIJeD5z5-Xf9MhIwsE~6e*VvK z0RVpeeC?lyVQCm>>1mCfjTbev64pjge2>*0;>&~b;1jqnA|gyCJWcl<3$bSnfQb)YDGE1W;@CkiNW zo7SKkP+cnqWY44z>T8R%{0myf*URAf(gZJHbf=bzS0pNASTT?-tDp>EH?t(_f`jow zw5;yYmX}qNSl6Xx>M*9lu5_z}%c|0K#$TQByUv)@Lsu5cT1(kEr4^gfWlINhBHBE+fW-Dg zX`>kyv0?pYui;ZNHGHWn=ZK5zEkDsFHEEe^k5zKDLVT)&?|`E2P%Qi5!`3p0>;=GV z{3ewv5BNa*xQRmbEs7T$-V+PX{3b^&dxM!(Qr-(3Rl!grtL|)ED~6g6{2hs(j6eF` z%^R^h-iLn9&xkWVav?@W3{<4NKmd-7?SRffJxhQLb>O%usk~H0+T*(44^Nv5b z>gHy5y|vk?$2c0-@HT0jcs5rK6L1zg{vu$j?7<)Y2i^w!IJOj|x{k#@R$O?b@-L=d zSR2~%nqUoO>t}$6V2BTefl4Thxraw`F0{{cZ$F_#Pa29>RtTjD}(JC;z`aPk< zgOW0k0hiP9!m3MzC(ZcIV5J-Ww?J{r<8F4HGXh|ZX6XULZt!ApfZC>gK*z=0D`)>4*zmEq|+aVRq~jvXP3E^&0Z@KBOa}zmTbO+b3w4 zQma^w&^}u+d=TTA81C&3bOdZ`38~H!@-yFjTh0r*jT0q*G^G8L zwu`DJqykY@Iqb;_NVBqhfuKQeG_HxJz$oy>YQ7>;w65W6{xX0kcJqA6&Y~c3LgMW9z-k-8sQ8)6{nwkSOb5{; zSoudITNo$V3{x1T^~Qd$4P2}KO9+sqOQIDeUXpAaL3GGY zLJ(p zW7<;`HSBve`&aA`KDbgtQ7Q#NJg2uQZS=hd?O?{A0$464j3jblC{n7gOd0HDIi`4C zqkr{%m@e1SaALZ>%beJ+Q7t%SbJK|ueWS;LsqF^}IlgPY%P+TIZaR@pLEAvtc*Sk+ ziF|l*n`lc;~m-?XFE4OzKsFS#0V#1%$)6Uu!GSNQE6T2yD@ zTvH#j%KhymvsVKN9h&15^>9=a7cLMR66#?wmnVzE0G$^Coz9C3OTi!=2Mk4u!exz- z!U!C2zZB0t0rFm^7zb+8|~i zK|=Qx$S%b^4i@k@k>Ju4Ty^Q%F$ zK59;b+VB4+WbuzZ3@iANDXpJ93<)Fv0L1?)Qyfj~?HrwdEOnfm7S*R?_DPYuj%#X_ zRn{dw4DW9R9pA= z$Hd0&Lczj9R4i0d5kv*WjsXT3YH$d}#%{fKCw8~jR_ylL9T?c%_5Rij4D56EIcN0w zzw`N=hx^>;Ip4MR+H0-d`%Fz4)#TWy2K6h~Ea-4%WzU||qkDTSnNq;{dDuFi9FOA1 zO$(Wla&7n8j`wT(c^uZRKYeIKfew`}G%f4a>g3phf!llkNWQ+i$X=TQucp=B;aB{U z!_MUces-yGGtTQm^Yz=47ry;gwP2M(-Htac`*lp<#7gaxL)%{M<=m-z`IkQbJ>R@w zY{@An_c=A{W1+JH>R=Okp?-s<_BXe$uyUW6x5SH!U22q651W^3nd_rQWj4OL_~hJ*TKmJEx6G4p`iy38 z9-EXyp%rSn6v&lxeZ?_3pLc1q?s`gB>oHvpmUvq~yg-CS#{n;Q75`DHS0<0{nmgU! z=iWB&?DM>vcE5OcGq_qn)j?bUt__I|or{!ZlD8g5;)z1rt@D>lF}=g*Y) z_V=|5t6eS8-7)LkCUraYx;3WhkL#N8_fjm!EY8w&XULsH*2A@93j5B>{`h#}xihx{ zRJHxQ_teil^j?#iJzfNQWvguU{paKcYln8&sfwNdu-URQPul;yox^X58={I$uZa(Ra2 z>KL3KTcOW>tm@t+dC%oIiyc#f^V@f-ZJYQ!v5e!DgyM;s-c!0Xy_98nxdq){TwAjA zVuPczw&$K(C+l5(+bpX`*?#CgY|D`)pU!-qFn2^)kG0z$Enc(!_S*^$VNWg&$&_ow zyrxB*3r|ieb|r4|bKSMA>+jSVY@v!dwYA*9tpy5(W?naG^6odEy39;ze=*bhpjr+M zrrs^IJAc{~|-|pAWGuEr{jn5DE-#%`ad@)Ok z)zLl{@$r+}X0@D@!(q?S?8|zVXmaw-h^Ny6kJ&yiwQ|>I^^Z>to4p9XP{pzDyj+%f z=hkjH$8OQ^L#4Gf%1#VBojbZv@lp+K8@->>;(f6f;|G7Ws9Sf`!_T?jITjzDuXM3| zvzA-VFP`b<=~0@45lx=fw5i*mShiE;z1G`V#ZA^Eo&IgPXW)QJUEXAWSG`4}duNif zC1pN0c>f~z^K(;9p9o26SombE3%;$Qn|pr=F1xsY!*7Gel<2>|{LUXi#ST44D7*Go zX6KN8jehPrySe#{O+Mz8DW zsk_-A|Gw`X^GB-MwM=}t*|F~2Q_E{~c~QS>cyw<4BAXi(s!z@Aar14_udf@s{8O-o zr$?@}mfqFRCePKCEj|B&Pm!B>XVyPcFZfYH%^jOJI(y8Svd}*BLi;%zyKSD|$!<-I zU+#as|J$?DZBx@CN6$U7`T8NSo^AC_MJnf=x~G!ovimb@XZ_gtLYa%devDkZ^XJ6h zcQ)l+5nOo0#Si_8&i#4x!>%39v#gHzg{gX$8-2fCt?IQJ#~&D&Yqz?Jx81b~H{RZy zQ^I9xkLsN~4n*sYtDnYp?!0g1HSL^MFS~nP%Jwv(sYL;+37XiS6K=Me-g8#0HWl+QY0TFI8Sp zqLf!BxBB5{##|45^{{JV)$6%8+CKDNck{`%+A}6zPVVnS1xVf%h}BHHFIjy6VDgUbC@_TU&F*0 zi`jR!46|yiKD^}dmi#YgSFIam{qR}E9O~oms|2o_Hown_>$y9x9yn)5wd6cyuZNvj zxwBJ;qWu=_INvn$k@0(e*Ld}zVnjd(mx~q4>MI=?+1Y#WSqHBT!}oMN^CQb*m#EJx zJ`P z(V+`N2IRE=aA;e<@+*9Y*!8~|H1$SQO5-BW*Tqg&9~<7~RH4zCYWP?AT6$l^*|nD& z^jI{ePLo#7$<5Ar-%_vmoo!p2mm}=$*Y>R*n^MGe?$ z^(P(8VShPz+0R`CzTNLT^y`X!Eo{#p@AdZdp=!~NTjOu^taZKd0>@3O4le0aEcVl- z%>_2>n}6En^@E_M;V%Mz6%Sg_|JJgw(Sh?S#Ec$)YfFc&JCcXzJHNN-xTF5BCw$3P z#%p-7348pqxvY&}_I2~jZncLk*y9|zJ$FF8Tm3&gThc$r%<6-`_4k*O8NM{n*VlK4KFD4A>adLi$9uT?W!F}zck{0OwU}Lt6KXXt z+&yC%+ z!-CJx%FWg!%^vA_ZRNeBZ*RY~+#HkpX3ZVm&M&gBSX8h~(uSo0p9`N&aN6t>+Tnd^ zzoZ&#j_i*p+V$P87tTKihOT)vDe3Bzp|AU%Z4}l}?|tF*kzW0eHn36EDRDDuIG37NYDj&x*RssvQHAs! z4m!R#ooHY4L)7d_3+xY!n)1oDZ=Qk?p}E?H&cCBJ%x*5CMk zyTNFm=ZEX9$Y0{$+!d2ft2tCJ@an)x@8?a!|9vZ-!p8Ru|CyLz zi@&B6a#2r6S>P@$dbkLu$#rLDP7~AH7iswMcIS zgk#w+N*yErF50vV?>0+&R~JsVC24h$jNlRiRr993Yfv@Z^m0UmIx;Ytd9|3}RaiZP z+?lDb((Qa1ODcSeMgqnkm2_{0w{-rYP`HoApLt)XaM85a4GO>HzORmsU>L&sp|w)u zk94rY_u9zXdgJ|4%$q{#?3EnXJ+T;%{QYvD83USs(s`c?o74~gv>|x4dTkx=`9hK8jsQxf( z`izvjHr#ZHWJayXm0FD--?Itot2;DH4_d0TkyTifxX#Hmc851iyoc~C4@N1IVd(vL z$f>ENa#2Ue$d!peJ3rZVr4QkahZC}8%8f5&rGY3_x@wRy^#;%8>r`g24wv2lgPLc< zxxEGarc%a;>oheDfMs5Q2&-{odvd1+xBbvWOR;%*lomw>m=BVbu={5(vA)|!|Q zU7(^i6R(_pP#&eCP7G`6LTv;rkI1;xyv_frc<6${3)eHw&J5JL+K8n*Ekv<8NU&JqkpI zT-1XubJ_wDoBt043P{rG+@BQV8VJZqJl0ITEe$e3Op2tZ%k=A6g^8)pgR&}H&|>hg zLFW;YPVA$N2?+60`)efJJpNgik4XrWxk$XMnO18B6q9!1iX($R+7oxbD|C5|hYgq& z5hhZ5jb5pVBUY93J)-Dt)wVD>+paX#rL#ixx;_d@X`Al$>WnCMgJ-hYJ4^3$kUm}k zqx+bD{x4uUVCX_~OKHEvgsE}q7)f6|^2%d=Cm6XpjBJzkF8(Ga92mg79_XjmYt{bY z%AxC`|55B7G&+Iw#MWEaAtq!8b8J2K%>1jPVCPUI0XCz=jx>>kdZm4oQs|Tc-~6rY z0jr17vK7~Gj0x5;1X~pqEdJy9*SDtu8jLcs-o0#GDu{YG)E)JWQU`F7040;H?-IXG zgrT?NsemW#mzb~u|Ju-aM~Apjx1zN=5*br(P4T9QF|YVfSRH_#c7E84b+@Q`!Om18>z7PDV6T0un;-+6>!mD(IvB?tys5|LBdBLY)FwJH7ISZJv z%BX{jIy@XT9}p%6P~4Zbe>GzpkXs4o~&vqK;DgYr~QJHPP1a?>MzKoC1c= z(=6Iw;6Etjhg*kHDAO-7q1k#dkIy*!BqsAgc;ax8C%SD;Wsn24Ag__O?aYC3TV{eX z5K&g$qz8FU6BO7`GKS(25fyH2@JzWrJlV`I(fZ^X#bTd87^)*jnQv!{``&EZxiRqz{(pAkH{edes;BcLnq;SslwBlOpqVyzYHE zn+qb4Mw)E2v`x-H@(9ErQyZk^1v1SP{AgG81|n899}lb0$%h#*Z80z7);B;CMFVNE zLPY8vS|}hH3TfeHY~OC`qg0YG z%f_xl0kT6pur2DBH)){AXdN%GDbu{X+_&yp)SbAOxC;NuXez_&9=K*xAH;1SD0o^v zPg$-)S@I)6u$`6(AB-GVO}IK<6X+JF4u_fLvR|v_@tvN7H5V*4`}s5WJ#3JJS>rzXo(kxT(nPAmWtu&*PLOly?6+Z^ittOe$NF5A$zUCWSuigI zoHfTA3G(Q_EPhv^#tDp1*#_ljCJ}`1Ee@5I9ib>o#KZRGEy{`z5{98#I(D_{1%Fu9 z5$?-&2F|8(TD59#{4kNBTOrnlCA7D}|ed3N1d8z6~idRctz55kNS?aJS6k}>4M|HP zjn4WUy{0%^%hJ}kDHLWk{2&{P0_64l={f3Vtm^Z<%6R<0cjIC6R8PZ{gkgD1lX)`uLle5D>w<@1@g)sY8%TePaXYd+_{1)h{tv zzq5%-HR>WQNTmM~69z?Q#PQ#5{wSg7<2?8(J>s2hRRh;#eB032tGUy+WZ4IePCjl_ zNu|ovL)fY&?97O1uM5*erZ$Frh5B{w^UD#<;5DQ|)>}W`VMuz7Mn);hs-FJwJqy6d zad=QX(=Rb0;$bQZGaQE51Z&?YO#tSC#X1ov|A@?;TfyHQ?1WCc6KLCkFuWcvxd}En|fEYSD$(Q16)+g2Z^!%ehY|oXibQ#^$k^WrYlW zjSlNQ=c15@Ph)$YAOz^9g$k7CTY~mC*uIgKR5Xs)~`&Uab$-#7NXB zWs<7L+?#qsfwQO$HW!9fPep`iIcbC5E%vg~c?X#A6&_1dXiye@1 zYxa96{TC!twjw?1Wq7%DuwFuY@`mNJSDpEeR{0j}$7;}{VJZakDjfAG;T(-ii8v0` zZJ`CL!AQ*ek@{qLg>Kh(`_+~-Q7L#JHCYmcVH{zuoFJ<`v$rjQ82H9L5?Xm8DaA)T4DvEZT-kb*sl)2j5wVa#+D1SZhAPT$%~O z*C11`mRUTZ!6Nu#1;!cnv^Tz-zF6&?I&b2olkVeh$~LP=a~SqLo|+7=MQ14%VrXPo|^L zntCm@P1;kwIP5PAZ;ea9kqF&2nm~W<^bb|4f3d;OCxA>d?W}dK1<2AnMD~uw5-!I3 zfz$(T&z}(@5glvPaGHTsQxHy5o+-dijhqO+uXwyHTyqF=ZXQgWS~Ilq{e(0_#icf@ zG`qtmHn(UyH~^#=JT?r`dkmLI0V6$WNkv{*)uA2w<*E&^YGVfZL4$udycDx|$6jrJ64+Y{U=P?+tze!#z?92|fZ zUc=TKb)YexsS<1Af63V8BUG<3!`f#BDg_Tar7&@t0OcRd0~81x5<47ayMTx7UL;Ky z0<@8VJVfK5g@7r^@=x5F)T36Rk104Ugo#E!*r6kdj~+wzm{JOF+Wb6&^v| z`uVSXAPg7T!*Y(0z%5Medh-WA!OM;)3|lwebAJ;>a$aX!15V4^!}Y+J zeyuf;vAp6$F7NYxEHJy^YpkF3+bhJ-{udr2%lBCYYN0$BtO~L~g98EvhF;Fd%X(cz z6xTE*hHqIF3{(P8Y^j!D(TH(2pd?e{jV1nhuc3n6fMWAfb7V^{Myk!2-eT{_>p-c2 zV)M1{VKK@_6K$CCRQTn6Q)pkjz4c!qQUq$11x3dC9IEG9-HQGNLWLFekT^ZBL>{`U- z3j#!hI!x11rw_x%VJv;aa>9zDOhJ7;#KU$RDkBCNQ%A({0Qaokv_62BOTol! z5`88F829w@Ag>?KTe=evD?r$(x4YK_T124-)Luv4!voE7s9XC6YKXRTu{Cu5x)6l< z7H*^-*z|eLO(+t8T4Lkk&Mh9pSsh9H0650odQF?P4~jJw58ID#J3S6mYA zLzm8o1h%T@-4zh@8uAxI;=n8jN1K}a=VVESCKT^%RsVZm$co?rhFbVnmheC`n;XgeKf?k0flX1ral%BqSbNS8jiFo?e-p}_!k(~-@H?V2<*h>SIp>( zeclcOWFH$ViKH~?b$SWE=IYd{o^U*yMNsCwxEQ9QX#Ey_?wup>V=p>BVlAvOoAF#uQ{&M zprV@<78_J!P;YDj8@}T6jC*Z3sM#mn?`{U_Jyc^o`u=M%3JYx7fEZeC;}vsPlRR}# zp;-06W8LZ8TOlh%*N2DL{jZy@H(o~@EO4hY?}P}+_V3^5#}PEY+!qkGy^8+8h4^5t zn06)dG+KUReF;a{xfr61&4pDz31BfH+DK=ep4QGemLBPO>FO_7XBaeNbK%0T0#IyZ zw1(?QL5n(mZjMr&M*d+L7rqG?eL}PW+_CAvf)$q1FseP)jmkrxv|nO^+fN}Qt*LV3 z_P1&F^wGBt_sI=gqj!iEB-0ODngZ9sh8SkJ0$yI0a=Bp_T%0jX_YNZF&Yf+NGg#ir%a4 zm-ig%CBC9>qlJf&yd zhHLLfSAnHX#-4e8p)pS+vD!b?Th#61#1wm$>-*jhAPU0EQM6 zDwo_q3di45OosdDty^~!N?E~h){Jtmos6`!<4&mygR)asM6@~E@n;t-ijWBG4U4>4l5w4`y#@^x4q}LDWVe)D+ia*| zpM{6rNHV=WOVbzz``A9n-g`i$^p+oM~3rBJD-PTFHj1|RD7VnNPwXpdT=Jz~A|`ydG@AGCGJ zz*GNH?V+$0(rOWZ6BB%=WB|43;F0R?GP?k&4mND*vW4ci&?^v(fV`$=;Nfzes6f6( zrCQtWdx7bL`REL>ZW=IMNPtd}##6g|mdm-U`6fdfOk)UQaNN8MtX2x4Y?UonWD+nm z1IdQ6&jKDs!V?moy53v@%tMhjUW<4bdw!t~oh+Qw4~U#_DpnhtB|J=BK4!;uuX;pA#l}c&5hQo=>ATF* z7A@$>dcwg+rPUldU&Z`48hhl0dbLnewy7F{tepVAv_@Llf%r>#VuZMNvIO;VLizT=lplN@i7ehi@(S zBXCkWF~ZIstUi^2=W9F%EfK@c7iK4v2VfHvvtpD=Ji~z~h4H-(7Z%d^s0&&gc3vjS z`3yMz)*x!GJi32;Mzhpk@vt@5`%(q~9T8Xei3u<^>@`DTBEp5;6@2+^M`2{AHli7x z8te@v^)Ct+K****S1z|kAJ1YDEsw-0MT%?B-vvmWE}NI=1gxE7QDoFa7_ zcIEjUsPPkSY{hs?-^W4-4)%uk^hejCXEgOKc(}uXUe7MVG`G<>vN}!2zH(Flgep85 z-P`C89;9C7T1$?hP}FH+%{)JQRu!C6>&t%h{<`w2?kjfTi5|o zEUcMo1L??B#=_<>c&|;qE_H)Y$Y4BmOogQ$;x5okcfAZhUp#T^v_pUpSgZzG_2p*6e9&$Xx&*rcmpS{3ry zD?|Q`*aSAtX9$#TUQCKjbIXyzE@^?l2M^o3`psd0I|9u5N2B6qg5A|L^T;{WNk-Y$ za{sAY;M3ADMmwfoVuE)GDL!lwt5GmW84rg=(?O$JtZJf?U+YUsbB$+;oiP6>p>CG} zAG$Y4ZBr{VSZ^%WQd$%RGKL?iNtQPpB^zu%YrE1G(A`M1jTq=D?08m!rutsmo>>{? zD|QN9(hoAqVdn|9=9_-7H7;FHk^|=s#y$b+wenr1_?rDy)s0oE$kD~Vo@CzR|$<9fjA=tQg}w^dmmOpVVW6EZ%WC&Uxq1BInzLdthc!3l}{-9 zY+zX%B#%%;;*6pum^*n&=%}8JOBMw75FR#XSdWrGr|k-Hj-|cke3y8iv*&r51Et;F z6_{EZI9dX0OwAG&_+0hnU20NuW3a?FP@l#~@H*4cH7SH-tPwE=ZhIU%4u1Tw8hpLZUV|EKpTvUT5!h-F8+}f(|l*l zmiiDg31aFqVm8h&LyQj7zG^yDBUhBjHYXpF3syq+qX{FU(QIWIhU{dj4c{mn)90>u zkyl>z$<@0IN;3ha!90oSmzYpvuCgRoT`Ug$D-@>AxKFBaC=A_B#a8_M`N|?_FN%VI zhowLCr!ovj8S0u!KzSg3p&0_Ou>)J2Wb5PH-p&p?L8fgu4HyY2i4f5>1febP#08D2WYuH&v^n|x_{wj8{Q?QZ;Dtt`M>r=b7#3#FHZ0#6$$*toc} zRvB+r=QpQcosN}Yp3BI#?u=8-T`wU*G!it9jN&Os%o-)E+OTc?ddRwhht2LbTO?$f zhKjHl|0V#+BXg@It;3!v)pYnS+mkQ7RSBG`xh(&ME^k;*RCRmIouL|m zIahYb5Hj@fGAw4QreLCu?P6s?%f)R)OcrY8>RDg56t+<(QYcgDU?sK>kcj)= zM54_un{;Ye9blc{O>Fln$3Z15j*&=Ey-r0`YKIV@Mw_J$Nm8QvYNT|nS|H0^+B_8r zDjT=Ojz~~5OfY!s6h>yXiaNxt03NFug50+KsF`@h(Vt^L@LrmsegYY6ZrF5OSw>qO zcC}!45-o-yj|%%TICC^0Bx9SOVRn_KbgWN_CN{7qrDnW3g1y~TNU2~78KQKNp+rYw zTdRmCKW#S$JmGb;L4tB%T$uVJ4fdqIArcfUcn$r~46h|;e2uTE5P-R%41mJeY(<(H z+p^D`4-LQ?wfGb(|%6v=cG4+9gLBYo+WVB`2O4Nk97Qd zHe@guVd2tesY##j5*SP~$7G!6!&Rz+`YNAhZNn6)J#JFrm>VfmuZzYpf6U!5S_x@v z;d=9Fk=TO8DkWdIm3&N;TCd~*tdZ{VIk>e%I87_mhxMf5XSqhgHxsbo1O``d0M@}f zNWsu}qy1y7EmVv3$w_=tbbw(?HUkn?8#@hsTmq!QjF{oZUxp=AinV#xb6i`+&|Ma+ z4+wQiU!@`kZ^Gvo_SIyZW~My)rhmD58n|^R9(J8t4~k$K+mwydlZ*5ub}!HqAHJ&Z zi9TRFoPzBX*qk?)E||imqSt5<>50}~)eZA5>F!3Oq8(ScCUlLBz%;wCJ<4GS@E!HM z#?vaj1N3AqulRiksq(tF%9gHD%RIV0#e zx7iW>+P@Qzt3eM$1H^Vs_dPU&?i--SO~*3Y2Y>soXG7Q~Cv3ycyz8Et!S_qu-zHk2 zC*6yGII~?3?kk)KsANj4REZy6D6_?NNwM{|h~EKM^lqEw6K*P6{ejD*4dS#LOUgkA zY8!I(3XW3_$>>?fE$^d4}CeO>axaw z(ln73qv^y<*?4W0QA6JJI_WrOYv#GVfJ0Raa5=Kd;W+zz2zPtd^<8~{dm_TE$S#Mo z=NI;nQ`P5J&>gk_j-Ai!jx9i(hB>vcZq&{j&TVrqbtFwgT7Fg2`OY7x_3Dfr2j!MS z(^W9?-5$>nt)jB zQpQEtvDib)7r5&&D!Ol{?tM{h@`4aBksr+^gih|4d1P##wH$@3D=At^E zd*tUeipig-7Pb+c?ruICrs7<4Nc>q{C*@j#m91llBqydiHsYfXT%Ss>a+B`hoBlcV zsuQuPNZj80>vnk}G;U#h(VP*tsmtGqGjubXihy5h(Did=u)!7;A5ojyX>t)TGdHnw-6C)yxTy+74&(XQz$|7!J{&+0cLLbnp{d9rK?r~*`V z4ztQV`%`f=W37};KIR;d^C-N(DLP`VOz}3n`Wt!51|2;u+^-2rH~=MdWF%gF_a_p~ zD4fl}dEF<#T}~q8+!#@jpZ`vjVy29Hcevwsh`f*7)r=9@0}0!FcS$duOrjhSvhFj^ z%c(3-d91MQI7jqH!j$W+VZZGaXlyb9#$<$xgV!L{&kQ zi|1th0~x-Ck1ohW*_~{67IwtWm`TCHY0nf3bL8-~kL@(%w;fW&bv*30kP!~%P-TYp z)KHB}EZb`#TwvsKA- zU*{fJhMj!--C9mUT9YcRKiOxT$Hj{ap+9|?n6*!lw&u{4w9kK}UmH5{Pu~Km!gx$p zUpcp2k;+Hrd$N9Y2_SDkSvH6Gb(TZYEz{Zn zZH&a)0NJ=++Xs*7GF{pt&E}9@UFFcJJrwB*BvW*3?*1>Wbl@zkAhnL`ZU$Vb{suN} zGT=1uJAtpt)ZhM|a(G$?lyGV?iS^=z6&e9~7tNV1gZ)n}hc#wZ8E}{0t$jy8Uu(eG zXz8Gl1*eXNpF_FM7u*F3w3ow3COkTpJw{N^Fpa|{YlQkKiOpZ~OAkVfe{$(7k2DCs4 z*zD4-FPClH^p@TVQ9SVz*CSuYwMZkX^H_akTh3r4bxv2;h)zu|(%jrLXVzZ?b#I_A zQIRo6t^^sbG;q(P2leQvBF+m6lJ@fv3P2BunS-{4hv;c*bax=x)}`}k1*Am2CRZzI zU!@tYxKYKy)!3YOVXO?*n46@_pMBd$pXX4t5$1x~oVR+S95yvGNrNlSyt8)&x{#N! zji>@sQ+KAyfZMAj#u|RxZ*{!^4rPl<4DZN%E-!6srOdt@@4Y`_sSU*ab%Hi9d4V!h zrdvv>ZSJBhrDEQcaB9JM)0aeU@pM}`T%4`ifBDc@mY6?AKS@(M?;2NM5QqNK3?9WF1#1vRQ9c#jiPJh#<;G6BKORU-?ed?kv6DpA1}1c7N;PHUAB#yF{<~pMGpA`HdBu`u zeB28s*#{?S!N{wy{jcR2yhKK5LS&N#^HFuys5*9r!}Z@k5t=qkz;XmGmFG-nQVEY( zME>^=gzZ2^WM^ob?)@8K=&6VsGZN(EIjeCB%s2)+4cIBLDhK~YkfGbc7qz#8)`w>9 z-$R@mQ)^+z|3p-VxkNYIUmq{y{{^&`6Y0AgS0U1c5ve=%mm=kp$^IG(JC8#oWWw4J zyZSQq>|Y9$%q6oYXFG5XKJpe0*_wB@c*FhNjF~Y>15&iS&--=dBr;Z=**6)I5$vL+$8&r7tCo@$%8ID{i^Z1^)Ki}ZUY$n%z`V*nD z6UmgxFMKOhH4vw}CSo+m4ojAQHBS&fAP&4-eQ^?;Vh0|U>yy`lH{40lP1Sr{Zt6K8AH#7VnGPz!Bd_Z24n*5o9L*ZrLCsr04sNuv zQ3T%{Ly~rt-G(qlcTF&`yi`Jt+#wQI$OTG%J)D%DlRNn9G5F?p9MNG%+?UEopwmw@ z(H>f#^b<~E9q62 zR0{sL$jM@=;q$MJLIhyCQ_wr+j{cMaFXOZzsoTQ88tF56G)8l9$-#@8!{ncz*dT zMqDi05%Ow79^3cx_xXEy=!x;gjf$zWGatmYKzGwQEsfxBVnXo_e=m-|Pm#O_@62PbG>aP*Zkl)v74k#QqYF!nW|+LM0@m zp4g>ppy=o>ZwiXYx!v*x=0`JZhuJ;0!*e9uJThNn{q^7e+wg_qN=>9Q+zRdgr zj|1a_?@pS}mhl-961r#nhN>|81_UQ-_JOClLQ+r28@5A8d`+IX1y@Gwpfwm=2P9a7 zcy(5m8yOIy)60N!IMuAEhD9y|UW2iU{{=a)VPYK9fimd0NyFv@0eu^2Hc{ofXa*Y7 zwi0lP9M|`Is%inJTL#&V^}$Pu@YKm0!x&#i#;E%#>Gw6zz=GTp zpM4XI^PfFb5|QSe(h*D&7G1IMrb38=Y{g@9CCHV63>Cg~M|b)lI87X~T?79VIT>i7 zB+O5m=eJm7mkCjo8=Xg6CaqaKlcO5ff@Q$x{m0qxow6Oa+e=N^Ag3kDkp@7=`y%JUWRCcE- zdG)vpUsVkw4b~~zf0U(C29Vr+w&_H!QTgE%b zbGV(6o_p2xaEm1=w9DsB`uTs%H|Y(AY>V`}GVVrxatZ3OV@(H-0aL@m_gQ zR|!x|2rWU#f~**grpbeFLwi&RgA@7#8V(b&HV2={$;pgKx;DV)$6>&lLP~!P`(segnB9@n0&G2yC z0jt4>k=PFqt+FFBpz#1 z4G`*ur6kHJGN!#cn$yi7y9{sA_u3WovuGOv%4_;1CfF6g#dT_2iyX+a$h6GkH~T^h z`kEfPXr^CcLaib>R3U~1TcH)(yVZC*IRWQ5A~Oj-B(}V04pk_Q%If25*wu8XX;(8s z8(A}y`B)7p+pL~LoCZRvBGdB>6+d`Z4ppQ&PK%ER==3#=)hSe)Vsh^jyV;r0@>jzh z%h)Saa7<2o`PGsJ#!=3Pl<(&%o**VqwN_Z_uTGPWoWZ1qVd4 zIN7Ta-R#sK{ZE#5^t6CR7r)a7W;@{1tP-?~Z7XH&hglOfl6!gzqJp-%z@Z@-icL>i zb-O7cT%JN~7B8iTbS|5&v6{F-QzFnMNWQ0RIHHj>uAVo3(y>p8*%6SD3n?}Zb60@XzDx zCd?x;NXIW`0f00oT0TuT{7p=7|H%XT;?qNPmo}gFVu^kkIg2>O2mO+x z8Fqa4m57Y+kGs$A1GE8DWIbo_Zvhnh>cTaWUtORSFmZN6$EAS%z{A4&sd8qVnei~* zLMIFRP`mE(4FHMjwo4`%n1rV^uCTA~MbNsVoNUy#$js8P+s7~x;#b1YZOsf7KwAje z2HPi#kV9XYmu&f?C*)i<3JNV3+3H|cAqY!bh6CpPq?(9k=L>h}4vhjaS;sbnBeJnD z-&iegI}z2ML!Nzm7DJnBB8`gSKHv=VY90oNe7v8W;<$W2K;#N+^8Uz!VRHnG#W%U_ z#iy17fSHO1-AdChG2wMiRxcX1@EP+CBL!U;#$gF-or z?PZ;jrOBq78NaiYZHKW&b4)3-<~vY`r=na7dLp@!^*|^%4-earv@R}YnUM=`J@Ij> zjJk+{f~6VzS9LB1O)^Fj*3xH*DIb>^GOHwg@B9ap zV_Va*HD##$1lXy{+$pq9*a$5I>)zYyF)-gSZIsNW6;doJtIfDwC@NNs1>X2y1C~XN zjhr_Q?|5PSZB*`VR4$umjy91Zx#(i?@e+P1lUB72!NiWLAxg@YGTDj4i;cwMmsE53 zAtks|YjEhG0Lz--!et>+c>9#dVsj4Vj&OzLcOtp4tNTUWC0VH-)S^bsM>!6khDHo` zL8WYiJKHmHvd&Xd1RSt$yqN;V7Map28upk3d$2utr#6xT3_XR8_%ymy1L)Wd5TX z;5Jx#6x8aAu_B^(3v0K&THMJVs7ZtKsUH|)6FF2qq)E+(p>8l5 z9oMSJ6n5ur4kUGo*}66N1_g@3h@_w1RRBDV@>XMjP4CG7seaKV(FM2hO#dl$WM8#+#cj&Nwx50jrIa%F7k zjHOlZ!*6yD^J(UN9IVOqM>M54G?_`+tNmBCdWe)2VkztZzbh>w8PlLtl0Dqc(!UxM z@_@gvedz+$QYeYh;=F1z_cjNLJ~+do;wnj@?D>X&vVP$~I&D(|g|su7ow^urt4N`Y z-2+TCDo>JG9?9LVE%0=@C*lno`mmHX!F1GofXYSA!(<|&aw`WZWF2DSz zTXt*R11YN`(sCuH{6k||5U$2`)_2=Zdq^&LQhjB zPsi5#o?{}QUjSv>w=aX_p)K^fSl;IsDd&_t)7E+(s1}GjmU?=KJXLOhk@aZN7kmS( zA1Y6k8UKIQ^(sKUSi1C0P*cO@p_DWDwcn(mL%<9$pNNd=gVn1H9qf!X<*dP?ghr;S zM(>^Wo2cJFt;*DY&Cv=}xw_i%@<#9yU~{3aSZwaG3Rt0%t@d*l4>FPSLVtJSfM(u^X$7YkclO&-`w&J@%qYFJf+@NeZQH3S{Bgw_V zH#It_aazeF6<_CFw?e?4#lwybbyFp=#><~Ifu<%-Vl3hEYE{B=fGHnXGfsAHnj~Cy zsC@I)!Q-?Co$leQzz}!LkR-N<)$%?NLb;`Z_i;}RID_!8xuw@ENnVEaKYm@+3}5@R zDzv2bj~%Pzo-IvfoFILPkuPF-bB{SR8S4o#=--%ri3y|TNQ=nm4@wepZ)w?LDY&2T zG&1q2)m=MRT7uX$l;jK!JP^AG{C9X*4_q-%T288$D8ZYq8Iq5tkq+TuYhv1bX*e^T zq$HyAqkdmr0v~~zsDZy}zr=*V1=1pL)sZ?vgXUD*PkMdpWB(4z7lHQ#4?8h5Z=o6J zXeHIBPhY-~BB>sFKI}=n@r$JSl>3y(ZDY1ItN?>l0-f!$#V(a6x1kTJ8`p@b>&Ex~ zK1G|3tPMP!HD%k`$BB~ov_6|evYLN&j1$%4Kj5;dpv!Vernk-`GSs-kl&`6J$li0W zL7f6B+Z;?-AxUNYkIyZ$p<;fTUZ%Wl1Af{sG2!q^X|CZblxogLKPVSwAF`?oZ3Rfd z!*&Tvua-ob{8+-O`>(%opeq`GW9r5#O-cMsOc=dJ5-Q!gss}AAN;C9Rp(ESB*tA|2 zC%-v6Q$p6`BadC#c$LlzI*5=Z4=N$+^O2b< z_SSj=IZlKeouq_x;3JoLmK#>Jj)b4v*+5syvJ&l#{EZrKKI$=3MnJ4#52c&xanQ~Aq4(*1-ia_&7P zq(nSw^X3>$T6&3)TOKGOCE{`X>)4XpfGj17$88T4kP<%R^fL6^e<02gDY^Es5>X-^ z?Nxg@_)j!Y8ScZ5kE{ezM#TAeewG;H9MA5EL z@|>vLg-R+BCE~H;&zTO5fz*kRn@TGoCF0R@#J3@|Y4WlNS*x59QX(GLX1DNm1u|BI zJZGhZl!(XsleZ*Pa^Er4x|XMFo$ms)Uq? z$9kjvY?=TWFG3cmu7s3`$37LtzxD<4f(SXerV>&j9(6JA!x{kDTZF7+r-YP<#|dAf z!^R>WZv$)1w2zDJ6_6699P;6C!!DqSJw2kH5>X-^FXyRylj2eA>A4yxAtmDRNY8c$ zLV(;VGUez-N=S)#Y`Sm7VA{hKBtqIdDj_A}acoTJSPhWdMaZOPN=S)#^!96gh_XhA z2pNWJiZd>fin=fLCF1c=_pPfd14+XPYsQD(xhfzfVyE-Sa@nYPq}~fl?Ak(sC=oi* zZ$=F&3F2T8alMBEQ6h5ua_e8sM&#I|C1Y1(a(O8bjh{7?J7IVH@{IqcVk_ptroz>` zH?8I2{Ar@i4f_AyhN}63r#w?dN!_?S4>|3u+Vp9#7nF)9K0CL(y}KOEOBtP@@4PHTiZ@Q&-o}f&1|qMLE#z(nDNdD7t`$;GP{$yrBs|6jrFAmmO`ug21}A@sirkfGiW8x zemq%Tb@d`x^>8+!E9H%p#YXd8DYE4G?)AXK_eurp6fdJBdC*P**Sm+^xL{OxN>1Tc zQgyT>&baIoZQWjntBc?PEj8iz$`fDT@x|P1szcv05K^0Q{Sti@1sJZvk=weo(Xn0V zKDYy2r*F;Br}k5#^Y#7Qt6}HLaDz7pe|B|k>HtY1u0@sif*RTPl%b<$1)--Eqo-<^ z995#$KG&>qlV)@)!KmyC*umip&U7V=;VNT%78?7^q|Tfzj);#R0jLI^#oE$ulmt}a z%x=@zMFTHE#TVEL%_gccWBEk7Psp$tNbZEm?W-?3{eUs2!IFh_^69ZF8*>s!ONqT zSTFjzMH1Co$Gh^05`Lr1Us7&j!(XfB!l{)0+xR#`)yPHrlM=^v2j@|#qOgm;BIDQLGls`zD zdBmHC9pUPWz-1$H^jit0^6r5;iFpcn=D@axLc-*1{mBfdVgH-a z9yXPdAZvoube2>T6QT=DJ0uLNOCJVIZ16M--BLnx)@)YzTt-4he55);8^Dja(Ys51 zB9*`ttN6W`mLm^C|E>u1P0 zY&b_-E2H^FcxylBOK+%4Q&4OZv$qbP=@t;K#hpAJbO&3IT520#(w)59;$YmxV6z*g z;_69o`$l2gPR1>aa{iWbX7!sL;M4WaHcaI;aggFG+^5j=)ACz5pry)QM3~v?H{>Hz zx4g+kT;UN{w$H(s;6GeHX3gli!#2-C+zNItoL3FRiHv-YxK7V{m@Lw5OSG`NhG* z_J4$RYN5HTnI;c^6B8N-nlF;izMrsejW;smDX`hj&VUd(w(M0TiEk|{e}j!^`hnfX zYZ)O2)myu$BViMFy)MGgKgHqTKy85JS}syLSy{@y0(Wm?qA%){R?U z_?F>8VNYUJtgIBin|x_9;m4}{2vYb6+pRi$h>tV+yYbwH+%ThM;UmZCu%QEN!N%y0 zi*jT+=8QXR#4OSbO5Ka*p6M228&Uxmq673=>05*vd+Tn|>A@o?0h?KW731^0b#0=kT`?sRENcx|NlH;(ki$-Tt;kr^eE>J3cWlh?ME&_&jExxb$GZqwmQNy#UURo*^58 z1u9B_aTTB*hlX%=C;%Tzl$zRF@c!W{+6YKr)nh|tS0z5UE$%*32Wt%T#Zs;uUM=PO zQ*>Y>;cAr_yVj_xOy$?rkP`9Mw7-yUN?<>y+@-M;GxdOmaa>?+YNgufwV0mgi`l>R zz}a(fhq@5McK3cenk9yhebB8;G<|=Fw!^X(Dbid48!ct!&36j~ZvYQlbOk44Iyx&d zjk&{Q5{VIHyQyVVS;Kbns zn3N^*c6NJ7i|&}&77Xq@0u-TqJ@X}fxoC_Jqt!&yHI;nowsG3> zNk|S(m|9{>e=Jm%8ZWaxb3IS*Z;og*FuV~=D4pxghZ=kPlGA`*4lzrv0GJ0rD<*tf z_mKd`MoQnyH~MCEr@1iYZxoze=d0OCc zch{81u?|SLm9RL#cHE2vfRt4_-XB*+<)b~3wIDYL+`O&=W zR_OK*?8xdiD@#6Z58BUoUosz8^?s-0!!ftl0ZEJX_i@?yxK0t_MxRXU)$+l$7oDBb z04o=ZL1ib=I+fysJF6okmVq1(gjmovwmFC$wuVpFlxCsb$2DPM?I_F}6fVB%A$(;3 zEXhtcc-rxaYSU%P(X|X0Oc+k=D;+RB@V?m1MD*q>Vw#Fw0T@-s3^^v5azoc`=ifVh zL^+PbI_w$i!7j=&Xw6lw6lAR)l}a40hvJNX|Q*Uq3*F z&~0^%nIQhy(hL!Xdn6QVgv#PK_-*_?z8H?oVeJTp)D zA4m!=ItK9lc-WKXle;Sm@ld+bCQ<+K{aBz6;$dedLVB2sm%A{fT#21C#&P-1J83JPRxaP7ziI_{d1YWIe1eeBG)w=RJ7NFQLxTYJZw728u&*-6vMmuN8L!8kBUW+ z*e3CjIg+Tol5I^WIo8xvW!-@qwHeY~Tz*%1z70S2J!4R`cAQN$|JFWXT8fFpayE$63`O+cRy7E(t6yVpw ziP#=V?@%-F>CKtZfJL;ysvIb&^@86whFMkRte$Lxi%13_PfhwXQt4L5@> zZJD?;c3y56&_A;hcBH07D1%$MdfL@XZ>!}p#+2#5gI~io#nG8!(^8#&W(vXwBvYGD zsqt+QZKHt45b_v(4^~LrfIk-^v1riw-RXsQQ4hT#i0u+?8uaHvQZIAmHx;9up7?yi zT;mrPq2E3q{KujsL`-?qWiv{$4klygkn7G-7GZMRbSL18(awwP@D@g+>o8fPInGlS z!z>9XiRv(`O3P@7p=~YfU~SBNWl`zVze;kR_SliF9punG1l3Tqv|nOE`-RGKunU+I z>onx3ZtLt(3`3`5g@psOmy49S6zX!ClY|)?qLvRweUHg0taHDW=1DN?KBKc0kG(F6 zaK{a_0t4Bt<%`L<55KKiD>0Vw*}nDpdRW^A#&=4yI{qdmOxnojn!W;Q+}4u1wII!T zQ}?<^C6#ASRDI|&xdEtWA4c4~P5+Cy^hHW+jK>ay;CO!Ml=E~uG7Pfut#effBfs31 z|5bjN#xPV!SB0ilQ#TOGYqjK^hetDLH4np}Fh;8?+yB34rHjS=!iJrV@``ntk;j%+ zQ?9~XT1K%qJO6jZjD5You-BRK{bo8rtwpd`IHT6j-T!~oGS^@u-!%Kr8S@UYnBr*0 zXm)(x|DYM)nU|dzywMJ3*oeH)lo1wu_-};Cby|-)q|CK}oUO<|Y{5Pp{To@nvHmgf zQ4-5oc6rMkc#E9+Gna50Jnj@ z(M3e5_1b7%q&q&B7^|1izQSIo4ZC0}f0&A$5cqsiPDVQ31>0J%wMEUZ_UyM_Msz?9 z4Mo+n9kWc=<@j!W)d2|mv@*yGsa&s7=l2lOUDTCXb3;yuN2KOY#JG=q^&tVa>L6;? zKHlPsN&POYZ@4;6(-up&d>dI!+pThh`gHvt+i%%-U!IFY8=4q=F%jSIat_CT!BSzn zSWT=%T_1BP?RXJ#Xo8L%4EZMW<)nUS*eOPbjo`FtIas5Yy*&PI_x6qzP>k#_6FYqs z|43GZ;TsOFx;~Mz_?VLavwU4Wj{Qkqk&h$=wEi1u;sRF(my*mB<`7VHe;bDi0V{uH4cT6L- zdOb|W=Ywn8oS8yrQt2zTY=3vcTX}Gr+4*l9oya540JZTnWFe*sC(*Y{LI`qFj!L9dGxfD z1slI?Z#WfVECWTid~C0p{Z4ZgHA7!$VOJQNmNG+@hf$7kPl{}upKYjXln+8K;9=8W zWNC8*$!&W%K55F8p>VS@s0}vIkC!onZJ4k%qX^HvcY9gGx2{1H+o@k{WrmoH35zO5 z)?D+#uX|O1slMW=%tVfrH6zQ|z4kDC;F=^*cu1{|`UTeSGaaxEcq%Z^(Kb9NZI8!} zHtuRGO|az1y)0`vD0ml7C5G3%5{GBd(Vmo)*qBSqsV=+wXM=%fAZ4%xKTuhgDK|t~ zseg342B52u71&VCWh)Ey(FEv%Bejwrp6pt-PfS^q{&jSw20|9u2frx? zWjBi~@Sv6~Q_cdO|Mbzmf$z2zS-{<17OG?c)$HGQegk|4;Hr!d46ZK^HaMzOqqM%| zk%e_J@_2@m2W&6wNJDe5K3@FX`l!U*H?yHCc4!FP%gMzIE+4wr;&%-i2joFlnpL)( zhZNLUS;nOVDI;9oQFaR*JKYR#V7X&F&EiTl%Z@*K*8KqPRuMO;wOL$yz8yC8nje1@ zmG-=ta3|aEHs)~o)M>dl^&gHZTaPNUVLU8%7b&Vjhz&e2&EFE0RT2#bo4Ee#DTkC> z`B}aq`1oKrfh|;JnKprPOu4AtUE{x><5A>|cvuHW36f(f1#Q3iU4~Q3@(T{Y&V%d; zmgO2_Hnp9R-uK&JWx^pFbc52>D<8x7T{|5w_XKt)~caeP!11abj!$@C$MfD5SkdM>1b z@BqOj!~~b8(=Z^*%)rbbC~1yM8ZMPeQmLuUb4xTqv|LJh@_^i*OFo6n%vTgzm}!Pu z-}@gNxik0P`FGy`od5A~j`O*{``hk*|JZK(7b}zW@Yk#p2+4-kzuRZi5rkv~T!%Kv zl?@zNlP=l3opZZ&If5!D!OiK+acL`?XSus)G~XyQ0y^&?-&v@^OV{_(b~aMFuZJyP zp{nBfIGCdhsfh0Dgzn_QF!zXKuL21Zu4?9!E!Fn`rSs6qT@2Y zeO}*|VD^F{X~WFe!(zs(H9Dg@OrOe_>m{AM`QwXLl5Z<-MXsbf4V(A!dCmIiY<-sZ z+;*rQ*!SR&bk$S#@v$VE;meMkTlrq8{CnWXU?zb%igNI`4me~+;Dh$5H~^?kZAzJr zz9xKYa?LoheV`wVN1tgeKIpJCi`FGAJzn!;>*-X$&J=8dRSfK5yL0&VVMnE~iOyRa z+{n#%326QOC@tk4=MzO^x|IzfKF=blXmR-v9UH%&W)Y=oN2D3Dq*(&al4{#M+hg8@ zAqN2LLyK9}s#uJE$A^{!Rh5me6y|(ciFmO3SB6Lz;F&j8z)YJQ;+weJBGgp5Wu`OX@nZFjt$-4A)^T^6tJxZ8JX{Pj7RtW~9K1;7N z>ae~a67~}Q!m5s?v?t*|Ix|hJHTscbZTK9cHTSapYu=rAPPT&pV_a=F{l+}}{{&!{ zHy}Uz{&bX=iAFe_s_=mp9h%Rc>7@i8(!9c?H!~LJO>shWqFRe@*7?P&mH5XpL&Pqx zcEqaXCe&@Smu>tQ+x+SB*hOql&l*c^#3*pK?dnE%bW}u?8u>a+)l@4sfAp2Qj!U7c zck%Y4RQ9NoBYupKTu`|CMY34ng4T!bq@VVZOSV{oEqS3|cH}WgOcvwlwq{fphkV&> zP3+XC&orQvy(opA9iP%wW+^0i#DUu3;u|Zrppct*X;p3N=CBY;pHFCt?y3ISYcM0b zzN_s*-|D9w@teS+vnqx4i}TzNcAq2c=nQP^Ef=5j65Gm=kA6Hg4D4ixPcN$<@8gL5 zBzK9`@0y+KVn7-B$dmLWa#Dz+GLQ()wb!5Z$%T@-c-T6V|6qp& zN!N19C}iv=jjJoN#gX>5i)js^4hta%Oogr#t@)uL65ZZoXwT`zw3rA-bP@0pZ?*e1wn;U&#=b%ed?DT!q$x!Jm_UY(^Q2Xzb~5jvye z5Du7pG=Dq7_YPh<25wK|a3eL?>p@0C@l8eX`taR1w_6;JEJ|+iq;t^!rpsoNDom7W z#8yoGs`_6a`6(2pINOF`-b}fLu*nI17ko7c>63hUhMv8ySi&RA`b>T6Mencp0q(M* zx9u=&)KU(ZY_Gu@T$94t@_zfYDl`eI#uqdd-Z1Cm$86FU@vxvW#)@Q~W>R5DTmx#p z3`DrK^)Z{;ZsgFSjhakRzI`~PK&gX5_W?`i#OF72kkZx!VDpe0bii7B=r*Y!)eY_=lwUk({h zE~r}t$$MH|j!bKP+qNS+%W*v+_V%sW+rS{bp#BtVn;VaXTq8#TvmydZtI)Y!jy7>L zg?`&zE*fKyCtqx}>_Ow-hy2f^Zq?P$NoR~m>CIc8b&y*iSygmYPGr^Mk)}@Ad+GH7WI?Paf}Ym$+*l45xe1;~Zuepx7$6Nn(&blwxryX-7%E1CWqr)1Yh(FPvE_Uk zKO4FSaZb*0)7i;G>6mE=9bR^-4H%hXM2~nH78z)-cuFOg%~o&g(!6!m?a(3cu{GQA zOg`B%&I!*+N#QMF{59{RSJF z2bi9XH6613VuDhu=4^j0QkI`1`$e^omDcguEg~!?SI9RNq_$CjUs0S`83n1UAT=F% zy|;<+0;p%?tk-q$i$2IggD6#$?Bqj7&(iC(I;_Uw;>k>j&T|aY@8e#$=Zr{!?da`` z*~Nc`&-RSDmvZ#}kQ|?GwpsYvU&g0P=THSYY4b^+hZmrWSY!{nRqu6(PmLL;oSlXh z0iDQ2&XvBXuOx5ae1*c_!+91Gx zvcdDWSK-fvupd&A^)Z_i|Kj7vDtR}tZ9G4v;R^EG71W-N<$oU+@W|>X+XaerBX*N3 zpr1!%&_^V`zRU;Gw(=troR$GHZr+)V3-&mR4C#rpcin>y$evL8(D>aN*@eZ(DXHg& zt4qjDWn`N^T~gGSvP-fQWC))l>L~c7L%i20r<5t1fWLdv3{ISwSMQ3zq#c7cq%CT^g!Ox3@+7jKj9k}EtHbHO zTsB)BIn}Ll7eEy^(P;>@1`=t;@*nWYj#`C}O5NLqL*5Fs3bedo&K~UH4B9d><1sE3 zHya7GJnW%I7`eYb8yy|Gy*cSBCJUe!mzG~hhUrQHrn{wO?FCS5q_$)!p4oDvMvqE` za@S(HfmW{4Lk^d1vaDm;vsI8bkR({jWbJxzs5#h<9fEjMW#D26l{x{tK{>M@iSE;G zlTW^1g!O2VeZ48Tgp5}k^>f0s%FH>~u_$evW{W)V(eaNjL%Hd&8rFcVkJ(h@V^6ho z9617x@zZ5q1b`ex_O^nE!xjfns60((NDR3jk#_?X>Ej24%#0z;-Z0R7DO!1;J#B){ zV03WH>Dz-Mg0=ueMD(G6`-AL&O6YL*mCJQwna2wk%lhE|~^rHx(GN63@%37JNh z@NBb$H~bcK6d`&BZ67^PIcI=lxY`h=ecV_J3Yovxr7RA4Yi)bm&ep2Gi3`DA8=Q>7 zOuc~a;Xh%(O89GrUDgd8DWpf{K{wbaAz+`cRz0c&cPc`d?sByV7qXjrFaq?2Z_|R7 zLTu7c^rqazGfISJ+i}+mGYVrtGlOQcNhrpS_T(f!8}>?EW6KiMSc4X!J0;r8I2Md~ zyBmqED`_Rs%MtK8%&X7?n%K#9AWN?R16(6ktD}|L94E+K--4(w6woP=(7JHT^lXIkk7)zhKV*xo?U52bri*_>k&n+c2VTApUui5n?bZHT#n4HXi;rJ^=nXCIa*X&y2A%qM9~FN52l^Xk9Wa2 z4@?u%iPvQK#sSy~zK{hzPxZk>M=rnn1k0F{KkIpdhg z(O~W*@A5R%x)Q^0y4H2)S=TY;Jd{S%zfOK>7dMyiv^G0mYP5s?An~@^M zpt`hOYp=0D6Qz#;uvxo5KGTmJ5;Y+w&^0`Goyj6olDyp2cf>s(CtroaIl(rvHs0XE z*mBja^gkB|)O?_@Ptp3AO|>qb&Bs-w^NUAh4eZ2HQzaCfZHrtUvjL^Kko zhs;X8>1W$7yfswBwwIL9PItflODMG12FVj?-TIhK%VK#nK?_fiHFXo?iUIl!FJ!bn zW|Q*-CNk#9^sn($1$riBN)&pPk0P8EfbY7k`QOqO5FE%szT72-&sOkzZY0KL|3it80YLN_#>nAah@#>UJY{X{^SP(Kh&I!V8!b@kGwbPk2=5jPK$DH#? zH_4XV-FRvH{^uV&Qd6gpE!zDSqnxH8p68<1N{=g^naKu{d8H^veyB<@oTx&-;B$1Q zX#IVvVqz!bTZ_z3E|Xe!n&fw*5xe)CFs`QaYegE9mWZrqU*9^Q9+sPzDG z^voZ6=&tt6M{}HqW)wpW>ti-`UGAwcLYvyu{sV&t1ScDlZ41rlP<3i5gpKjUhnB6s zBwqOG8tZTM(&{#P7Y2jv@8_mof4>C3Z;wt89NGGqO=F7eexGjl^YClAFBjrRL*Q(* xuKI3x{Bu^ZWz$>76Ek_^rFHe4^>;?4Ap-@rhTCD3;55kToVtY~cq1yR_yZ;af}sEa literal 0 HcmV?d00001 diff --git a/test/org/broadinstitute/compositetask/MyTest.java b/test/org/broadinstitute/compositetask/MyTest.java new file mode 100644 index 0000000..b2f2400 --- /dev/null +++ b/test/org/broadinstitute/compositetask/MyTest.java @@ -0,0 +1,14 @@ +import org.testng.annotations.Test; +import static org.testng.AssertJUnit.*; +import org.broadinstitute.compositetask.CompositeTask; + +public class MyTest +{ + @Test + public void testTrivial() + { + assertEquals(3, 3); + assertEquals(0, 0); + assertEquals(4, 4); + } +} From bbbd2361ec13994fcc428cb4e7d41b752f690195 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 18 Sep 2012 15:42:23 -0400 Subject: [PATCH 082/140] 2 spaces -> 4 spaces --- .../compositetask/CompositeTask.java | 638 ++++++++++----------- 1 file changed, 319 insertions(+), 319 deletions(-) diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index d70ae57..287bfc9 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -13,364 +13,364 @@ public class CompositeTask implements CompositeTaskScope { - private ParseTree parse_tree; - private Ast ast; - private WdlSyntaxErrorFormatter error_formatter; - private Set nodes; - private String name; - private CompositeTaskScope parent; - - private class CompositeTaskAstVerifier { - private WdlSyntaxErrorFormatter syntaxErrorFormatter; - private Map variables; - private Map output_variables; - private Map output_files; - private Map step_names; - - CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { - this.syntaxErrorFormatter = syntaxErrorFormatter; - this.variables = new HashMap(); - this.output_variables = new HashMap(); - this.output_files = new HashMap(); - this.step_names = new HashMap(); - } + private ParseTree parse_tree; + private Ast ast; + private WdlSyntaxErrorFormatter error_formatter; + private Set nodes; + private String name; + private CompositeTaskScope parent; + + private class CompositeTaskAstVerifier { + private WdlSyntaxErrorFormatter syntaxErrorFormatter; + private Map variables; + private Map output_variables; + private Map output_files; + private Map step_names; + + CompositeTaskAstVerifier(WdlSyntaxErrorFormatter syntaxErrorFormatter) { + this.syntaxErrorFormatter = syntaxErrorFormatter; + this.variables = new HashMap(); + this.output_variables = new HashMap(); + this.output_files = new HashMap(); + this.step_names = new HashMap(); + } + + public Ast verify(AstNode wdl_ast) throws SyntaxError { + Ast composite_task = null; + + if ( wdl_ast instanceof AstList ) { + if ( ((AstList) wdl_ast).size() != 1 ) { + throw new SyntaxError("Source code must contain only one top level composite_task definition."); + } + + composite_task = (Ast) ((AstList) wdl_ast).get(0); + } else if (wdl_ast instanceof Ast) { + composite_task = (Ast) wdl_ast; + String node_type = composite_task.getName(); + if (!node_type.equals("CompositeTask")) { + throw new SyntaxError("Source code does not contain a composite task definition"); + } + } else { + throw new SyntaxError("Unknown syntax error"); + } + + AstList ctNodes = (AstList) composite_task.getAttribute("body"); + CompositeTask.this.nodes = new LinkedHashSet(); + CompositeTask.this.name = ((Terminal) composite_task.getAttribute("name")).getSourceString(); + + for ( AstNode ctNode : ctNodes ) { + Ast node = (Ast) ctNode; + CompositeTask.this.nodes.add(verify(node)); + } + + set_parents(CompositeTask.this); + + return composite_task; + } - public Ast verify(AstNode wdl_ast) throws SyntaxError { - Ast composite_task = null; + private void set_parents(CompositeTaskScope scope) { + for ( CompositeTaskNode node : scope.getNodes() ) { + node.setParent(scope); + if ( node instanceof CompositeTaskScope ) { + set_parents((CompositeTaskScope) node); + } + } + } - if ( wdl_ast instanceof AstList ) { - if ( ((AstList) wdl_ast).size() != 1 ) { - throw new SyntaxError("Source code must contain only one top level composite_task definition."); + private CompositeTaskVariable make_variable(String name, String member) { + String key = name + ((member == null) ? "" : member); + if ( !this.variables.containsKey(key) ) { + this.variables.put(key, new CompositeTaskVariable(name, member)); + } + return this.variables.get(key); } - composite_task = (Ast) ((AstList) wdl_ast).get(0); - } else if (wdl_ast instanceof Ast) { - composite_task = (Ast) wdl_ast; - String node_type = composite_task.getName(); - if (!node_type.equals("CompositeTask")) { - throw new SyntaxError("Source code does not contain a composite task definition"); + private CompositeTaskVariable ast_to_variable(Ast ast) { + Terminal name = (Terminal) ast.getAttribute("name"); + Terminal member = (Terminal) ast.getAttribute("member"); + return make_variable(name.getSourceString(), (member == null) ? null : member.getSourceString()); } - } else { - throw new SyntaxError("Unknown syntax error"); - } - AstList ctNodes = (AstList) composite_task.getAttribute("body"); - CompositeTask.this.nodes = new LinkedHashSet(); - CompositeTask.this.name = ((Terminal) composite_task.getAttribute("name")).getSourceString(); + private CompositeTaskNode verify(Ast ast) throws SyntaxError { + if ( ast.getName().equals("Step") ) { + return verify_step(ast); + } else if ( ast.getName().equals("ForLoop") ) { + return verify_for(ast); + } else if ( ast.getName().equals("CompositeTask") ) { + return verify_composite_task(ast); + } else { + throw new SyntaxError("Unknown node found in abstract syntax tree."); + } + } - for ( AstNode ctNode : ctNodes ) { - Ast node = (Ast) ctNode; - CompositeTask.this.nodes.add(verify(node)); - } + private CompositeTaskStep verify_step(Ast step) throws SyntaxError { + Ast task = (Ast) step.getAttribute("task"); + Terminal task_name = getTaskName(task); + Terminal task_version = getTaskVersion(task); - set_parents(CompositeTask.this); + if ( task_version == null ) { + throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); + } - return composite_task; - } + CompositeTaskSubTask subtask = new CompositeTaskSubTask( + task_name.getSourceString(), + task_version.getSourceString() + ); - private void set_parents(CompositeTaskScope scope) { - for ( CompositeTaskNode node : scope.getNodes() ) { - node.setParent(scope); - if ( node instanceof CompositeTaskScope ) { - set_parents((CompositeTaskScope) node); + Terminal name_terminal; + if ( step.getAttribute("name") != null ) { + name_terminal = (Terminal) step.getAttribute("name"); + } else { + name_terminal = task_name; + } + + String name = name_terminal.getSourceString(); + if ( this.step_names.containsKey(name) ) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_step_names(name_terminal, this.step_names.get(name))); + } + this.step_names.put(name, name_terminal); + + Set step_inputs = new LinkedHashSet(); + Set step_outputs = new LinkedHashSet(); + + AstList body = (AstList) step.getAttribute("body"); + + if ( body != null ) { + for ( AstNode entry : body ) { + Ast entry_ast = (Ast) entry; + + if ( entry_ast.getName().equals("StepInputList") ) { + AstList input_list = (AstList) entry_ast.getAttribute("inputs"); + for ( AstNode input_node : input_list ) { + Ast input = (Ast) input_node; + Terminal parameter = (Terminal) input.getAttribute("parameter"); + CompositeTaskVariable variable = ast_to_variable((Ast) input.getAttribute("value")); + step_inputs.add( new CompositeTaskStepInput(parameter.getSourceString(), variable) ); + } + } + + if ( entry_ast.getName().equals("StepOutputList") ) { + AstList output_list = (AstList) entry_ast.getAttribute("outputs"); + for ( AstNode output_node : output_list ) { + Ast output = (Ast) output_node; + Terminal filepath = (Terminal) output.getAttribute("file"); + CompositeTaskVariable variable = ast_to_variable((Ast) output.getAttribute("as")); + + Terminal var_terminal = (Terminal) ((Ast) output.getAttribute("as")).getAttribute("name"); + if (this.output_variables.containsKey(variable)) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_variable(var_terminal, this.output_variables.get(variable))); + } else { + this.output_variables.put(variable, var_terminal); + } + + if (this.output_files.containsKey(filepath.getSourceString())) { + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_file(filepath, this.output_files.get(filepath.getSourceString()))); + } else { + this.output_files.put(filepath.getSourceString(), filepath); + } + + step_outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); + } + } + } + } + + return new CompositeTaskStep(name, subtask, step_inputs, step_outputs); + } + + private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { + Set nodes = new HashSet(); + + String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); + String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); + CompositeTaskVariable collection_var = make_variable(collection, null); + CompositeTaskVariable item_var = make_variable(item, null); + + for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { + CompositeTaskNode sub_node = verify((Ast) for_sub_node); + + if ( sub_node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) sub_node; + boolean found = false; + for ( CompositeTaskStepInput input : step.getInputs() ) { + if (input.getVariable().getName().equals(item_var.getName())) { + found = true; + } + } + + if ( !found ) { + throw new SyntaxError(this.syntaxErrorFormatter.step_doesnt_use_loop_iterator((Terminal) for_node_ast.getAttribute("item"), this.step_names.get(step.getName()))); + } + } + + nodes.add(sub_node); + } + + return new CompositeTaskForLoop(collection_var, item_var, nodes); + } + + private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { + Set nodes = new LinkedHashSet(); + Terminal ctName = (Terminal) ast.getAttribute("name"); + + for ( AstNode sub : (AstList) ast.getAttribute("body") ) { + nodes.add( verify((Ast) sub) ); + } + + return new CompositeTask(ctName.getSourceString(), nodes); + } + + private Terminal getTaskName(Ast task) { + return (Terminal) task.getAttribute("name"); + } + + private Terminal getTaskVersion(Ast task) { + AstList task_attrs = (AstList) task.getAttribute("attributes"); + + if ( task_attrs != null ) { + for ( AstNode task_attr : task_attrs ) { + Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); + Terminal value = (Terminal) ((Ast) task_attr).getAttribute("value"); + if ( key.getSourceString().equals("version") ) { + return value; + } + } + } + + return null; } - } } - private CompositeTaskVariable make_variable(String name, String member) { - String key = name + ((member == null) ? "" : member); - if ( !this.variables.containsKey(key) ) { - this.variables.put(key, new CompositeTaskVariable(name, member)); - } - return this.variables.get(key); + /** Constructors **/ + + private CompositeTask(String name, Set nodes) { + this.name = name; + this.nodes = nodes; + this.parent = null; } - private CompositeTaskVariable ast_to_variable(Ast ast) { - Terminal name = (Terminal) ast.getAttribute("name"); - Terminal member = (Terminal) ast.getAttribute("member"); - return make_variable(name.getSourceString(), (member == null) ? null : member.getSourceString()); + public CompositeTask(SourceCode source_code) throws SyntaxError { + this.error_formatter = new WdlSyntaxErrorFormatter(); + this.error_formatter.setSourceCode(source_code); + ParseTreeNode node = getParseTree(source_code); + this.parse_tree = (ParseTree) node; + AstList ast_list = (AstList) node.toAst(); + CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); + this.ast = verifier.verify(ast_list); + this.parent = null; } - private CompositeTaskNode verify(Ast ast) throws SyntaxError { - if ( ast.getName().equals("Step") ) { - return verify_step(ast); - } else if ( ast.getName().equals("ForLoop") ) { - return verify_for(ast); - } else if ( ast.getName().equals("CompositeTask") ) { - return verify_composite_task(ast); - } else { - throw new SyntaxError("Unknown node found in abstract syntax tree."); - } + public CompositeTask(File source_code) throws SyntaxError, IOException { + this(new WdlSourceCode(source_code)); } - private CompositeTaskStep verify_step(Ast step) throws SyntaxError { - Ast task = (Ast) step.getAttribute("task"); - Terminal task_name = getTaskName(task); - Terminal task_version = getTaskVersion(task); - - if ( task_version == null ) { - throw new SyntaxError(this.syntaxErrorFormatter.missing_version(task_name)); - } - - CompositeTaskSubTask subtask = new CompositeTaskSubTask( - task_name.getSourceString(), - task_version.getSourceString() - ); - - Terminal name_terminal; - if ( step.getAttribute("name") != null ) { - name_terminal = (Terminal) step.getAttribute("name"); - } else { - name_terminal = task_name; - } - - String name = name_terminal.getSourceString(); - if ( this.step_names.containsKey(name) ) { - throw new SyntaxError(this.syntaxErrorFormatter.duplicate_step_names(name_terminal, this.step_names.get(name))); - } - this.step_names.put(name, name_terminal); - - Set step_inputs = new LinkedHashSet(); - Set step_outputs = new LinkedHashSet(); - - AstList body = (AstList) step.getAttribute("body"); - - if ( body != null ) { - for ( AstNode entry : body ) { - Ast entry_ast = (Ast) entry; - - if ( entry_ast.getName().equals("StepInputList") ) { - AstList input_list = (AstList) entry_ast.getAttribute("inputs"); - for ( AstNode input_node : input_list ) { - Ast input = (Ast) input_node; - Terminal parameter = (Terminal) input.getAttribute("parameter"); - CompositeTaskVariable variable = ast_to_variable((Ast) input.getAttribute("value")); - step_inputs.add( new CompositeTaskStepInput(parameter.getSourceString(), variable) ); - } - } - - if ( entry_ast.getName().equals("StepOutputList") ) { - AstList output_list = (AstList) entry_ast.getAttribute("outputs"); - for ( AstNode output_node : output_list ) { - Ast output = (Ast) output_node; - Terminal filepath = (Terminal) output.getAttribute("file"); - CompositeTaskVariable variable = ast_to_variable((Ast) output.getAttribute("as")); - - Terminal var_terminal = (Terminal) ((Ast) output.getAttribute("as")).getAttribute("name"); - if (this.output_variables.containsKey(variable)) { - throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_variable(var_terminal, this.output_variables.get(variable))); - } else { - this.output_variables.put(variable, var_terminal); - } - - if (this.output_files.containsKey(filepath.getSourceString())) { - throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_file(filepath, this.output_files.get(filepath.getSourceString()))); - } else { - this.output_files.put(filepath.getSourceString(), filepath); - } - - step_outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); - } - } - } - } + public CompositeTask(String source_code, String resource) throws SyntaxError { + this(new WdlSourceCode(source_code, resource)); + } + + /** Public Methods **/ - return new CompositeTaskStep(name, subtask, step_inputs, step_outputs); + public ParseTree getParseTree() { + return this.parse_tree; } - private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { - Set nodes = new HashSet(); - - String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); - String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); - CompositeTaskVariable collection_var = make_variable(collection, null); - CompositeTaskVariable item_var = make_variable(item, null); - - for ( AstNode for_sub_node : (AstList) for_node_ast.getAttribute("body") ) { - CompositeTaskNode sub_node = verify((Ast) for_sub_node); - - if ( sub_node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) sub_node; - boolean found = false; - for ( CompositeTaskStepInput input : step.getInputs() ) { - if (input.getVariable().getName().equals(item_var.getName())) { - found = true; - } - } - - if ( !found ) { - throw new SyntaxError(this.syntaxErrorFormatter.step_doesnt_use_loop_iterator((Terminal) for_node_ast.getAttribute("item"), this.step_names.get(step.getName()))); - } - } + public String getName() { + return this.name; + } - nodes.add(sub_node); - } + public Set getNodes() { + return this.nodes; + } - return new CompositeTaskForLoop(collection_var, item_var, nodes); + public CompositeTaskGraph getGraph() { + return new CompositeTaskGraph(this); } - private CompositeTask verify_composite_task(Ast ast) throws SyntaxError { - Set nodes = new LinkedHashSet(); - Terminal ctName = (Terminal) ast.getAttribute("name"); + public CompositeTaskStep getStep(String name) { + return getStep(this, name); + } - for ( AstNode sub : (AstList) ast.getAttribute("body") ) { - nodes.add( verify((Ast) sub) ); - } + public Set getTasks() { + return getTasks(this); + } - return new CompositeTask(ctName.getSourceString(), nodes); + public Ast getAst() { + return this.ast; } - private Terminal getTaskName(Ast task) { - return (Terminal) task.getAttribute("name"); + public void setName(String name) { + this.name = name; } - private Terminal getTaskVersion(Ast task) { - AstList task_attrs = (AstList) task.getAttribute("attributes"); + public void addNode(CompositeTaskNode node) { + } - if ( task_attrs != null ) { - for ( AstNode task_attr : task_attrs ) { - Terminal key = (Terminal) ((Ast) task_attr).getAttribute("key"); - Terminal value = (Terminal) ((Ast) task_attr).getAttribute("value"); - if ( key.getSourceString().equals("version") ) { - return value; - } - } - } + public void setParent(CompositeTaskScope parent) { + this.parent = parent; + } - return null; + public CompositeTaskScope getParent() { + return this.parent; } - } - - /** Constructors **/ - - private CompositeTask(String name, Set nodes) { - this.name = name; - this.nodes = nodes; - this.parent = null; - } - - public CompositeTask(SourceCode source_code) throws SyntaxError { - this.error_formatter = new WdlSyntaxErrorFormatter(); - this.error_formatter.setSourceCode(source_code); - ParseTreeNode node = getParseTree(source_code); - this.parse_tree = (ParseTree) node; - AstList ast_list = (AstList) node.toAst(); - CompositeTaskAstVerifier verifier = new CompositeTaskAstVerifier(this.error_formatter); - this.ast = verifier.verify(ast_list); - this.parent = null; - } - - public CompositeTask(File source_code) throws SyntaxError, IOException { - this(new WdlSourceCode(source_code)); - } - - public CompositeTask(String source_code, String resource) throws SyntaxError { - this(new WdlSourceCode(source_code, resource)); - } - - /** Public Methods **/ - - public ParseTree getParseTree() { - return this.parse_tree; - } - - public String getName() { - return this.name; - } - - public Set getNodes() { - return this.nodes; - } - - public CompositeTaskGraph getGraph() { - return new CompositeTaskGraph(this); - } - - public CompositeTaskStep getStep(String name) { - return getStep(this, name); - } - - public Set getTasks() { - return getTasks(this); - } - - public Ast getAst() { - return this.ast; - } - - public void setName(String name) { - this.name = name; - } - - public void addNode(CompositeTaskNode node) { - } - - public void setParent(CompositeTaskScope parent) { - this.parent = parent; - } - - public CompositeTaskScope getParent() { - return this.parent; - } - - public boolean contains(CompositeTaskNode node) { - for ( CompositeTaskNode sub_node : this.nodes ) { - if ( node.equals(sub_node) ) { - return true; - } - - if ( sub_node instanceof CompositeTaskScope ) { - CompositeTaskScope scope = (CompositeTaskScope) sub_node; - if ( scope.contains(node) ) { - return true; + + public boolean contains(CompositeTaskNode node) { + for ( CompositeTaskNode sub_node : this.nodes ) { + if ( node.equals(sub_node) ) { + return true; + } + + if ( sub_node instanceof CompositeTaskScope ) { + CompositeTaskScope scope = (CompositeTaskScope) sub_node; + if ( scope.contains(node) ) { + return true; + } + } } - } + return false; } - return false; - } - - public String toString() { - return "[CompositeTask name="+this.name+"]"; - } - - /** Private methods **/ - - private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { - WdlParser parser = new WdlParser(this.error_formatter); - Lexer lexer = new Lexer(); - List terminals = lexer.getTokens(source_code); - TokenStream tokens = new TokenStream(terminals); - return parser.parse(tokens); - } - - private static Set getTasks(CompositeTaskScope scope) { - Set tasks = new HashSet(); - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - tasks.add(step.getTask()); - } else if ( node instanceof CompositeTaskScope ) { - CompositeTaskScope subScope = (CompositeTaskScope) node; - tasks.addAll( getTasks(subScope) ); - } + + public String toString() { + return "[CompositeTask name="+this.name+"]"; } - return tasks; - } - - private static CompositeTaskStep getStep(CompositeTaskScope scope, String name) { - for ( CompositeTaskNode node : scope.getNodes() ) { - if ( node instanceof CompositeTaskStep ) { - CompositeTaskStep step = (CompositeTaskStep) node; - if ( step.getName().equals(name) ) { - return step; + + /** Private methods **/ + + private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { + WdlParser parser = new WdlParser(this.error_formatter); + Lexer lexer = new Lexer(); + List terminals = lexer.getTokens(source_code); + TokenStream tokens = new TokenStream(terminals); + return parser.parse(tokens); + } + + private static Set getTasks(CompositeTaskScope scope) { + Set tasks = new HashSet(); + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + tasks.add(step.getTask()); + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskScope subScope = (CompositeTaskScope) node; + tasks.addAll( getTasks(subScope) ); + } } - } else if ( node instanceof CompositeTaskScope ) { - CompositeTaskStep step = getStep((CompositeTaskScope) node, name); - if ( step != null ) { - return step; + return tasks; + } + + private static CompositeTaskStep getStep(CompositeTaskScope scope, String name) { + for ( CompositeTaskNode node : scope.getNodes() ) { + if ( node instanceof CompositeTaskStep ) { + CompositeTaskStep step = (CompositeTaskStep) node; + if ( step.getName().equals(name) ) { + return step; + } + } else if ( node instanceof CompositeTaskScope ) { + CompositeTaskStep step = getStep((CompositeTaskScope) node, name); + if ( step != null ) { + return step; + } + } } - } + return null; } - return null; - } } From 42d92287d756c21f2a68db602a2b6ee5236788d8 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 18 Sep 2012 15:46:41 -0400 Subject: [PATCH 083/140] renaming test file --- .../broadinstitute/compositetask/CompositeTaskTest.java | 12 ++++++++++++ test/org/broadinstitute/compositetask/MyTest.java | 14 -------------- 2 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 test/org/broadinstitute/compositetask/CompositeTaskTest.java delete mode 100644 test/org/broadinstitute/compositetask/MyTest.java diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/test/org/broadinstitute/compositetask/CompositeTaskTest.java new file mode 100644 index 0000000..94ef158 --- /dev/null +++ b/test/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -0,0 +1,12 @@ +import org.testng.annotations.Test; +import static org.testng.AssertJUnit.*; +import org.broadinstitute.compositetask.CompositeTask; + +public class CompositeTaskTest +{ + @Test + public void test() + { + + } +} diff --git a/test/org/broadinstitute/compositetask/MyTest.java b/test/org/broadinstitute/compositetask/MyTest.java deleted file mode 100644 index b2f2400..0000000 --- a/test/org/broadinstitute/compositetask/MyTest.java +++ /dev/null @@ -1,14 +0,0 @@ -import org.testng.annotations.Test; -import static org.testng.AssertJUnit.*; -import org.broadinstitute.compositetask.CompositeTask; - -public class MyTest -{ - @Test - public void testTrivial() - { - assertEquals(3, 3); - assertEquals(0, 0); - assertEquals(4, 4); - } -} From 6ae4c1b4caeae26618eba05642ae1a1588490228 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 18 Sep 2012 19:36:39 -0400 Subject: [PATCH 084/140] work in progress --- build.xml | 16 ++++- .../compositetask/CompositeTaskTest.java | 74 ++++++++++++++++++++-- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/build.xml b/build.xml index 7abdccb..bfa9a69 100644 --- a/build.xml +++ b/build.xml @@ -52,8 +52,9 @@ - - + + + @@ -61,13 +62,22 @@ - + + + + + + + + + + diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/test/org/broadinstitute/compositetask/CompositeTaskTest.java index 94ef158..aafb8c5 100644 --- a/test/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/test/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -1,12 +1,76 @@ +package org.broadinstitute.compositetask; + import org.testng.annotations.Test; -import static org.testng.AssertJUnit.*; +import org.testng.annotations.DataProvider; +import org.testng.Assert; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.ArrayList; + import org.broadinstitute.compositetask.CompositeTask; +import org.broadinstitute.compositetask.SyntaxError; public class CompositeTaskTest { - @Test - public void test() - { - + @DataProvider(name="parsingTests") + public Object[][] parsingTests() { + File parsingTestDir = new File(System.getProperty("test.files"), "parsing"); + Collection composite_tasks = new ArrayList(); + + for ( String subDir : parsingTestDir.list() ) { + composite_tasks.add(new Object[] { new File(parsingTestDir, subDir) }); + } + + return composite_tasks.toArray(new Object[0][]); + } + + @Test(dataProvider="parsingTests") + public void testLexicalAnalysis(File dir) { + File tokens = new File(dir, "tokens"); + if ( !tokens.exists() ) { + System.out.println("Created " + tokens); + } + } + + @Test(dataProvider="parsingTests") + public void testParseTree(File dir) { + File source = new File(dir, "source.wdl"); + File parsetree = new File(dir, "parsetree"); + CompositeTask ctask = null; + + try { + ctask = new CompositeTask(source); + } catch(SyntaxError error) { + Assert.fail("Not expecting syntax error: " + error); + } catch(IOException error) { + Assert.fail("IOException reading file: " + error); + } + + if ( !parsetree.exists() ) { + try { + FileWriter out = new FileWriter(parsetree); + out.write(ctask.getParseTree().toPrettyString()); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write " + parsetree + ": " + error); + } + System.out.println("Created " + parsetree); + } + } + + @Test(dataProvider="parsingTests") + public void testAbstractSyntaxTree(File dir) { + File ast = new File(dir, "ast"); + if ( !ast.exists() ) { + System.out.println("Created " + ast); + } + } + + @Test + public void testTrivial() { + Assert.assertEquals(1, 1); } } From ac4c31d1a9c5350b5897dfba363735ed27fbd8cb Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 19 Sep 2012 15:24:33 -0400 Subject: [PATCH 085/140] More unit testing framework --- build.xml | 2 +- .../broadinstitute/compositetask/SyntaxError.java | 4 +- test-files/parsing/0/ast | 186 ++++++++++ test-files/parsing/0/parsetree | 367 ++++++++++++++++++ test-files/parsing/0/source.wdl | 24 ++ test-files/parsing/1/ast | 203 ++++++++++ test-files/parsing/1/parsetree | 410 +++++++++++++++++++++ test-files/parsing/1/source.wdl | 30 ++ .../compositetask/CompositeTaskTest.java | 41 ++- 9 files changed, 1257 insertions(+), 10 deletions(-) create mode 100644 test-files/parsing/0/ast create mode 100644 test-files/parsing/0/parsetree create mode 100644 test-files/parsing/0/source.wdl create mode 100644 test-files/parsing/1/ast create mode 100644 test-files/parsing/1/parsetree create mode 100644 test-files/parsing/1/source.wdl diff --git a/build.xml b/build.xml index bfa9a69..40dd2dc 100644 --- a/build.xml +++ b/build.xml @@ -76,7 +76,7 @@ - + diff --git a/src/org/broadinstitute/compositetask/SyntaxError.java b/src/org/broadinstitute/compositetask/SyntaxError.java index b42f680..8312fba 100644 --- a/src/org/broadinstitute/compositetask/SyntaxError.java +++ b/src/org/broadinstitute/compositetask/SyntaxError.java @@ -1,7 +1,7 @@ - package org.broadinstitute.compositetask; + public class SyntaxError extends Exception { - SyntaxError(String message) { + public SyntaxError(String message) { super(message); } } diff --git a/test-files/parsing/0/ast b/test-files/parsing/0/ast new file mode 100644 index 0000000..4d8e427 --- /dev/null +++ b/test-files/parsing/0/ast @@ -0,0 +1,186 @@ +(CompositeTask: + body=[ + (Step: + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (ForLoop: + body=[ + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + item=identifier, + collection=identifier + ), + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + name=identifier +) \ No newline at end of file diff --git a/test-files/parsing/0/parsetree b/test-files/parsing/0/parsetree new file mode 100644 index 0000000..a730f07 --- /dev/null +++ b/test-files/parsing/0/parsetree @@ -0,0 +1,367 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/0/source.wdl b/test-files/parsing/0/source.wdl new file mode 100644 index 0000000..c994a2a --- /dev/null +++ b/test-files/parsing/0/source.wdl @@ -0,0 +1,24 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=item, p2=GLOBAL; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=item, p2=y; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/test-files/parsing/1/ast b/test-files/parsing/1/ast new file mode 100644 index 0000000..39510d6 --- /dev/null +++ b/test-files/parsing/1/ast @@ -0,0 +1,203 @@ +(CompositeTask: + body=[ + (Step: + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (ForLoop: + body=[ + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ), + (ForLoop: + body=[ + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + item=identifier, + collection=identifier + ) + ], + item=identifier, + collection=identifier + ), + (Step: + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + member=None, + name=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + as=(Variable: + member=None, + name=identifier + ), + file=string + ) + ] + ) + ], + task=(Task: + attributes=[ + (TaskAttribute: + value=number, + key=identifier + ) + ], + name=identifier + ), + name=None + ) + ], + name=identifier +) \ No newline at end of file diff --git a/test-files/parsing/1/parsetree b/test-files/parsing/1/parsetree new file mode 100644 index 0000000..75ce2e2 --- /dev/null +++ b/test-files/parsing/1/parsetree @@ -0,0 +1,410 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + as, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/1/source.wdl b/test-files/parsing/1/source.wdl new file mode 100644 index 0000000..e92a322 --- /dev/null +++ b/test-files/parsing/1/source.wdl @@ -0,0 +1,30 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=item, p1=global; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + + for ( alpha in beta ) { + step dtask[version=0] { + input: p0=alpha; + } + } + } + + step gtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/test/org/broadinstitute/compositetask/CompositeTaskTest.java index aafb8c5..b63ad6c 100644 --- a/test/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/test/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -27,10 +27,29 @@ return composite_tasks.toArray(new Object[0][]); } + private CompositeTask getCompositeTask(File source) { + try { + return new CompositeTask(source); + } catch(IOException error) { + Assert.fail("IOException reading file: " + error); + } catch(SyntaxError error) { + Assert.fail("Not expecting syntax error: " + error); + } + + return null; + } + @Test(dataProvider="parsingTests") public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); if ( !tokens.exists() ) { + SourceCode code = new WdlSourceCode(new File(args[0])); + Lexer lexer = new Lexer(); + List terminals = lexer.getTokens(code); + System.out.println("["); + System.out.println(Utility.join(terminals, ",\n")); + System.out.println("]"); + System.out.println("Created " + tokens); } } @@ -39,14 +58,10 @@ public void testLexicalAnalysis(File dir) { public void testParseTree(File dir) { File source = new File(dir, "source.wdl"); File parsetree = new File(dir, "parsetree"); - CompositeTask ctask = null; + CompositeTask ctask = getCompositeTask(source); - try { - ctask = new CompositeTask(source); - } catch(SyntaxError error) { - Assert.fail("Not expecting syntax error: " + error); - } catch(IOException error) { - Assert.fail("IOException reading file: " + error); + if ( ctask == null ) { + Assert.fail("Null Composite Task"); } if ( !parsetree.exists() ) { @@ -57,14 +72,26 @@ public void testParseTree(File dir) { } catch (IOException error) { Assert.fail("Could not write " + parsetree + ": " + error); } + System.out.println("Created " + parsetree); } } @Test(dataProvider="parsingTests") public void testAbstractSyntaxTree(File dir) { + File source = new File(dir, "source.wdl"); File ast = new File(dir, "ast"); + CompositeTask ctask = getCompositeTask(source); + if ( !ast.exists() ) { + try { + FileWriter out = new FileWriter(ast); + out.write(ctask.getAst().toPrettyString()); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write " + ast + ": " + error); + } + System.out.println("Created " + ast); } } From aca06e3334cba54837e945aee0de630e0eda49a3 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 19 Sep 2012 15:33:58 -0400 Subject: [PATCH 086/140] Refactoring --- src/org/broadinstitute/compositetask/CompositeTask.java | 4 ++-- .../{WdlSourceCode.java => CompositeTaskSourceCode.java} | 10 +++++----- ...odeFormatter.java => CompositeTaskSourceCodeFormatter.java} | 6 +++--- src/org/broadinstitute/compositetask/Lexer.java | 2 +- src/org/broadinstitute/compositetask/WdlMain.java | 6 +++--- test/org/broadinstitute/compositetask/CompositeTaskTest.java | 4 +++- 6 files changed, 17 insertions(+), 15 deletions(-) rename src/org/broadinstitute/compositetask/{WdlSourceCode.java => CompositeTaskSourceCode.java} (84%) rename src/org/broadinstitute/compositetask/{WdlSourceCodeFormatter.java => CompositeTaskSourceCodeFormatter.java} (95%) diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index 287bfc9..2c1c464 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -261,11 +261,11 @@ public CompositeTask(SourceCode source_code) throws SyntaxError { } public CompositeTask(File source_code) throws SyntaxError, IOException { - this(new WdlSourceCode(source_code)); + this(new CompositeTaskSourceCode(source_code)); } public CompositeTask(String source_code, String resource) throws SyntaxError { - this(new WdlSourceCode(source_code, resource)); + this(new CompositeTaskSourceCode(source_code, resource)); } /** Public Methods **/ diff --git a/src/org/broadinstitute/compositetask/WdlSourceCode.java b/src/org/broadinstitute/compositetask/CompositeTaskSourceCode.java similarity index 84% rename from src/org/broadinstitute/compositetask/WdlSourceCode.java rename to src/org/broadinstitute/compositetask/CompositeTaskSourceCode.java index 9c526d1..029515c 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCode.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskSourceCode.java @@ -12,7 +12,7 @@ import java.util.List; import java.io.FileInputStream; -public class WdlSourceCode implements SourceCode{ +public class CompositeTaskSourceCode implements SourceCode{ private File source; private String resource; private String contents; @@ -21,19 +21,19 @@ private StringBuilder currentLine; private List lines; - WdlSourceCode(String source, String resource) { + CompositeTaskSourceCode(String source, String resource) { init(source, resource); } - WdlSourceCode(File source) throws IOException { + CompositeTaskSourceCode(File source) throws IOException { this(source, "utf-8", source.getCanonicalPath()); } - WdlSourceCode(File source, String resource) throws IOException { + CompositeTaskSourceCode(File source, String resource) throws IOException { this(source, "utf-8", resource); } - WdlSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { + CompositeTaskSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { FileChannel channel = new FileInputStream(source).getChannel(); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); Charset cs = Charset.forName(encoding); diff --git a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java b/src/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java similarity index 95% rename from src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java rename to src/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java index f17a1ce..f5afe2d 100644 --- a/src/org/broadinstitute/compositetask/WdlSourceCodeFormatter.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java @@ -3,14 +3,14 @@ import java.util.ArrayList; import java.util.List; -public class WdlSourceCodeFormatter { +public class CompositeTaskSourceCodeFormatter { private CompositeTaskColorizer colorizer; - WdlSourceCodeFormatter(CompositeTaskColorizer colorizer) { + CompositeTaskSourceCodeFormatter(CompositeTaskColorizer colorizer) { this.colorizer = colorizer; } - WdlSourceCodeFormatter() { + CompositeTaskSourceCodeFormatter() { this(new NullColorizer()); } diff --git a/src/org/broadinstitute/compositetask/Lexer.java b/src/org/broadinstitute/compositetask/Lexer.java index c31910f..344a643 100644 --- a/src/org/broadinstitute/compositetask/Lexer.java +++ b/src/org/broadinstitute/compositetask/Lexer.java @@ -101,7 +101,7 @@ LexerMatch match(SourceCode source) { } public static void main(String[] args) { try { - SourceCode code = new WdlSourceCode(new File(args[0])); + SourceCode code = new CompositeTaskSourceCode(new File(args[0])); Lexer lexer = new Lexer(); List terminals = lexer.getTokens(code); System.out.println("["); diff --git a/src/org/broadinstitute/compositetask/WdlMain.java b/src/org/broadinstitute/compositetask/WdlMain.java index 220057e..3003741 100644 --- a/src/org/broadinstitute/compositetask/WdlMain.java +++ b/src/org/broadinstitute/compositetask/WdlMain.java @@ -56,15 +56,15 @@ public static void main(String[] args) { } } else if ( args[1].equals("format-ansi") ) { - WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(new AnsiColorizer()); + CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(new AnsiColorizer()); String formatted = formatter.format(ctask); System.out.println(formatted); } else if ( args[1].equals("format-html") ) { - WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(new HtmlColorizer()); + CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(new HtmlColorizer()); String formatted = formatter.format(ctask); System.out.println(formatted); } else if ( args[1].equals("format") ) { - WdlSourceCodeFormatter formatter = new WdlSourceCodeFormatter(); + CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(); String formatted = formatter.format(ctask); System.out.println(formatted); } else { diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/test/org/broadinstitute/compositetask/CompositeTaskTest.java index b63ad6c..cd16abf 100644 --- a/test/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/test/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -43,12 +43,14 @@ private CompositeTask getCompositeTask(File source) { public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); if ( !tokens.exists() ) { - SourceCode code = new WdlSourceCode(new File(args[0])); + /* + SourceCode code = new CompositeTaskSourceCode(new File(args[0])); Lexer lexer = new Lexer(); List terminals = lexer.getTokens(code); System.out.println("["); System.out.println(Utility.join(terminals, ",\n")); System.out.println("]"); + */ System.out.println("Created " + tokens); } From 815a975d43f92c0bd00f1b772bbdd27956c7ca4b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 21 Sep 2012 15:53:12 -0400 Subject: [PATCH 087/140] First unit tests --- .travis.yml | 2 + test-files/parsing/0/tokens | 128 ++++++++++++++++++ test-files/parsing/1/tokens | 143 +++++++++++++++++++++ .../compositetask/CompositeTaskTest.java | 60 +++++++-- 4 files changed, 320 insertions(+), 13 deletions(-) create mode 100644 .travis.yml create mode 100644 test-files/parsing/0/tokens create mode 100644 test-files/parsing/1/tokens diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..25720ea --- /dev/null +++ b/.travis.yml @@ -0,0 +1,2 @@ +language: java +script: ant test diff --git a/test-files/parsing/0/tokens b/test-files/parsing/0/tokens new file mode 100644 index 0000000..308d6b4 --- /dev/null +++ b/test-files/parsing/0/tokens @@ -0,0 +1,128 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "R0xPQkFM"}, + {"terminal": "semi", "line": 9, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 20, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 21, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 21, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 21, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 21, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 21, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 24, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/1/tokens b/test-files/parsing/1/tokens new file mode 100644 index 0000000..49b2aec --- /dev/null +++ b/test-files/parsing/1/tokens @@ -0,0 +1,143 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 25, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 25, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 26, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 26, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 26, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 27, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="} +] diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/test/org/broadinstitute/compositetask/CompositeTaskTest.java index cd16abf..b06dad6 100644 --- a/test/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/test/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -9,9 +9,14 @@ import java.io.IOException; import java.util.Collection; import java.util.ArrayList; +import java.util.List; import org.broadinstitute.compositetask.CompositeTask; import org.broadinstitute.compositetask.SyntaxError; +import org.broadinstitute.compositetask.SourceCode; +import org.broadinstitute.compositetask.CompositeTaskSourceCode; +import org.broadinstitute.compositetask.Lexer; +import org.broadinstitute.compositetask.Terminal; public class CompositeTaskTest { @@ -42,18 +47,36 @@ private CompositeTask getCompositeTask(File source) { @Test(dataProvider="parsingTests") public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); - if ( !tokens.exists() ) { - /* - SourceCode code = new CompositeTaskSourceCode(new File(args[0])); + File source = new File(dir, "source.wdl"); + String actual = null; + + try { + SourceCode code = new CompositeTaskSourceCode(source); Lexer lexer = new Lexer(); List terminals = lexer.getTokens(code); - System.out.println("["); - System.out.println(Utility.join(terminals, ",\n")); - System.out.println("]"); - */ + actual = "[\n " + Utility.join(terminals, ",\n ") + "\n]\n"; + } catch (IOException error) { + Assert.fail("Could not read source code: " + error); + } + + if ( !tokens.exists() ) { + try { + FileWriter out = new FileWriter(tokens); + out.write(actual); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write tokens file: " + error); + } System.out.println("Created " + tokens); } + + try { + String expected = Utility.readFile(tokens.getAbsolutePath()); + Assert.assertEquals(actual, expected, "Tokens list did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + tokens.getAbsolutePath()); + } } @Test(dataProvider="parsingTests") @@ -61,6 +84,7 @@ public void testParseTree(File dir) { File source = new File(dir, "source.wdl"); File parsetree = new File(dir, "parsetree"); CompositeTask ctask = getCompositeTask(source); + String actual = ctask.getParseTree().toPrettyString(); if ( ctask == null ) { Assert.fail("Null Composite Task"); @@ -69,7 +93,7 @@ public void testParseTree(File dir) { if ( !parsetree.exists() ) { try { FileWriter out = new FileWriter(parsetree); - out.write(ctask.getParseTree().toPrettyString()); + out.write(actual); out.close(); } catch (IOException error) { Assert.fail("Could not write " + parsetree + ": " + error); @@ -77,6 +101,13 @@ public void testParseTree(File dir) { System.out.println("Created " + parsetree); } + + try { + String expected = Utility.readFile(parsetree.getAbsolutePath()); + Assert.assertEquals(actual, expected, "Parse trees did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + parsetree.getAbsolutePath()); + } } @Test(dataProvider="parsingTests") @@ -84,11 +115,12 @@ public void testAbstractSyntaxTree(File dir) { File source = new File(dir, "source.wdl"); File ast = new File(dir, "ast"); CompositeTask ctask = getCompositeTask(source); + String actual = ctask.getAst().toPrettyString(); if ( !ast.exists() ) { try { FileWriter out = new FileWriter(ast); - out.write(ctask.getAst().toPrettyString()); + out.write(actual); out.close(); } catch (IOException error) { Assert.fail("Could not write " + ast + ": " + error); @@ -96,10 +128,12 @@ public void testAbstractSyntaxTree(File dir) { System.out.println("Created " + ast); } - } - @Test - public void testTrivial() { - Assert.assertEquals(1, 1); + try { + String expected = Utility.readFile(ast.getAbsolutePath()); + Assert.assertEquals(actual, expected, "Abstract syntax trees did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + ast.getAbsolutePath()); + } } } From b640ee16f49f02295b515bfa7358e444f1ebdbc1 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 21 Sep 2012 15:57:05 -0400 Subject: [PATCH 088/140] YAGNI --- src/org/jgrapht/alg/AbstractPathElement.java | 202 ---- src/org/jgrapht/alg/AbstractPathElementList.java | 196 ---- src/org/jgrapht/alg/BellmanFordIterator.java | 448 ------- src/org/jgrapht/alg/BellmanFordPathElement.java | 150 --- src/org/jgrapht/alg/BellmanFordShortestPath.java | 239 ---- src/org/jgrapht/alg/BiconnectivityInspector.java | 138 --- src/org/jgrapht/alg/BlockCutpointGraph.java | 365 ------ src/org/jgrapht/alg/BronKerboschCliqueFinder.java | 198 ---- src/org/jgrapht/alg/ChromaticNumber.java | 147 --- src/org/jgrapht/alg/ConnectivityInspector.java | 302 ----- src/org/jgrapht/alg/CycleDetector.java | 271 ----- src/org/jgrapht/alg/DijkstraShortestPath.java | 218 ---- src/org/jgrapht/alg/DirectedNeighborIndex.java | 233 ---- src/org/jgrapht/alg/EdmondsBlossomShrinking.java | 194 ---- src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java | 361 ------ src/org/jgrapht/alg/EulerianCircuit.java | 148 --- .../jgrapht/alg/FloydWarshallShortestPaths.java | 317 ----- src/org/jgrapht/alg/HamiltonianCycle.java | 120 -- src/org/jgrapht/alg/KShortestPaths.java | 258 ----- src/org/jgrapht/alg/KShortestPathsIterator.java | 416 ------- .../jgrapht/alg/KruskalMinimumSpanningTree.java | 126 -- src/org/jgrapht/alg/NeighborIndex.java | 262 ----- src/org/jgrapht/alg/RankingPathElement.java | 115 -- src/org/jgrapht/alg/RankingPathElementList.java | 436 ------- src/org/jgrapht/alg/StoerWagnerMinimumCut.java | 283 ----- .../jgrapht/alg/StrongConnectivityInspector.java | 393 ------- src/org/jgrapht/alg/TransitiveClosure.java | 138 --- src/org/jgrapht/alg/VertexCovers.java | 157 --- src/org/jgrapht/alg/package.html | 6 - src/org/jgrapht/alg/util/UnionFind.java | 168 --- .../jgrapht/alg/util/VertexDegreeComparator.java | 134 --- src/org/jgrapht/alg/util/package.html | 6 - .../event/ConnectedComponentTraversalEvent.java | 103 -- src/org/jgrapht/event/EdgeTraversalEvent.java | 93 -- src/org/jgrapht/event/GraphChangeEvent.java | 93 -- src/org/jgrapht/event/GraphEdgeChangeEvent.java | 169 --- src/org/jgrapht/event/GraphListener.java | 74 -- src/org/jgrapht/event/GraphVertexChangeEvent.java | 119 -- src/org/jgrapht/event/TraversalListener.java | 100 -- .../jgrapht/event/TraversalListenerAdapter.java | 93 -- src/org/jgrapht/event/VertexSetListener.java | 77 -- src/org/jgrapht/event/VertexTraversalEvent.java | 93 -- src/org/jgrapht/event/package.html | 7 - src/org/jgrapht/experimental/GraphReader.java | 181 --- src/org/jgrapht/experimental/GraphSquare.java | 219 ---- src/org/jgrapht/experimental/GraphTests.java | 118 -- .../experimental/PartiteRandomGraphGenerator.java | 171 --- .../jgrapht/experimental/RandomGraphHelper.java | 126 -- .../experimental/UniformRandomGraphGenerator.java | 115 -- .../experimental/alg/ApproximationAlgorithm.java | 17 - .../jgrapht/experimental/alg/ExactAlgorithm.java | 13 - .../experimental/alg/IntArrayGraphAlgorithm.java | 49 - .../alg/color/BrownBacktrackColoring.java | 99 -- .../experimental/alg/color/GreedyColoring.java | 185 --- .../experimental/dag/DirectedAcyclicGraph.java | 1199 ------------------- .../equivalence/EquivalenceComparator.java | 93 -- .../equivalence/EquivalenceComparatorChain.java | 71 -- .../EquivalenceComparatorChainBase.java | 167 --- .../experimental/equivalence/EquivalenceSet.java | 206 ---- .../equivalence/EquivalenceSetCreator.java | 262 ----- .../equivalence/UniformEquivalenceComparator.java | 80 -- .../jgrapht/experimental/equivalence/package.html | 6 - .../AbstractExhaustiveIsomorphismInspector.java | 423 ------- .../AdaptiveIsomorphismInspectorFactory.java | 268 ----- .../EquivalenceIsomorphismInspector.java | 325 ------ .../isomorphism/GraphIsomorphismInspector.java | 95 -- .../experimental/isomorphism/GraphOrdering.java | 232 ---- .../isomorphism/IsomorphismRelation.java | 151 --- .../PermutationIsomorphismInspector.java | 148 --- .../VertexDegreeEquivalenceComparator.java | 178 --- .../jgrapht/experimental/isomorphism/package.html | 6 - src/org/jgrapht/experimental/package.html | 11 - .../permutation/ArrayPermutationsIter.java | 56 - .../permutation/CollectionPermutationIter.java | 185 --- .../permutation/CompoundPermutationIter.java | 307 ----- .../permutation/IntegerPermutationIter.java | 311 ----- .../permutation/PermutationFactory.java | 98 -- .../jgrapht/experimental/permutation/package.html | 6 - .../generate/CompleteBipartiteGraphGenerator.java | 119 -- .../jgrapht/generate/CompleteGraphGenerator.java | 139 --- src/org/jgrapht/generate/EmptyGraphGenerator.java | 95 -- src/org/jgrapht/generate/GraphGenerator.java | 80 -- src/org/jgrapht/generate/GridGraphGenerator.java | 145 --- .../jgrapht/generate/HyperCubeGraphGenerator.java | 118 -- src/org/jgrapht/generate/LinearGraphGenerator.java | 124 -- src/org/jgrapht/generate/RandomGraphGenerator.java | 381 ------ src/org/jgrapht/generate/RingGraphGenerator.java | 106 -- .../jgrapht/generate/ScaleFreeGraphGenerator.java | 154 --- src/org/jgrapht/generate/StarGraphGenerator.java | 116 -- src/org/jgrapht/generate/WheelGraphGenerator.java | 155 --- src/org/jgrapht/generate/package.html | 6 - src/org/jgrapht/graph/AbstractBaseGraph.java | 1222 -------------------- src/org/jgrapht/graph/AbstractGraph.java | 322 ------ src/org/jgrapht/graph/AsUndirectedGraph.java | 209 ---- .../jgrapht/graph/AsUnweightedDirectedGraph.java | 100 -- src/org/jgrapht/graph/AsUnweightedGraph.java | 100 -- src/org/jgrapht/graph/AsWeightedGraph.java | 147 --- src/org/jgrapht/graph/ClassBasedEdgeFactory.java | 91 -- src/org/jgrapht/graph/ClassBasedVertexFactory.java | 79 -- src/org/jgrapht/graph/DefaultDirectedGraph.java | 86 -- .../graph/DefaultDirectedWeightedGraph.java | 85 -- src/org/jgrapht/graph/DefaultEdge.java | 91 -- src/org/jgrapht/graph/DefaultGraphMapping.java | 135 --- src/org/jgrapht/graph/DefaultListenableGraph.java | 524 --------- src/org/jgrapht/graph/DefaultWeightedEdge.java | 77 -- src/org/jgrapht/graph/DirectedGraphUnion.java | 109 -- src/org/jgrapht/graph/DirectedMaskSubgraph.java | 64 - src/org/jgrapht/graph/DirectedMultigraph.java | 82 -- src/org/jgrapht/graph/DirectedPseudograph.java | 80 -- src/org/jgrapht/graph/DirectedSubgraph.java | 158 --- .../jgrapht/graph/DirectedWeightedMultigraph.java | 84 -- .../jgrapht/graph/DirectedWeightedSubgraph.java | 83 -- src/org/jgrapht/graph/EdgeReversedGraph.java | 187 --- src/org/jgrapht/graph/EdgeSetFactory.java | 73 -- src/org/jgrapht/graph/GraphDelegator.java | 298 ----- src/org/jgrapht/graph/GraphPathImpl.java | 122 -- src/org/jgrapht/graph/GraphUnion.java | 288 ----- src/org/jgrapht/graph/IntrusiveEdge.java | 82 -- src/org/jgrapht/graph/ListenableDirectedGraph.java | 83 -- .../graph/ListenableDirectedWeightedGraph.java | 84 -- .../jgrapht/graph/ListenableUndirectedGraph.java | 83 -- .../graph/ListenableUndirectedWeightedGraph.java | 85 -- src/org/jgrapht/graph/MaskEdgeSet.java | 149 --- src/org/jgrapht/graph/MaskFunctor.java | 72 -- src/org/jgrapht/graph/MaskSubgraph.java | 298 ----- src/org/jgrapht/graph/MaskVertexSet.java | 134 --- src/org/jgrapht/graph/Multigraph.java | 85 -- src/org/jgrapht/graph/ParanoidGraph.java | 110 -- src/org/jgrapht/graph/Pseudograph.java | 84 -- src/org/jgrapht/graph/SimpleDirectedGraph.java | 82 -- .../jgrapht/graph/SimpleDirectedWeightedGraph.java | 83 -- src/org/jgrapht/graph/SimpleGraph.java | 85 -- src/org/jgrapht/graph/SimpleWeightedGraph.java | 82 -- src/org/jgrapht/graph/Subgraph.java | 546 --------- src/org/jgrapht/graph/UndirectedGraphUnion.java | 81 -- src/org/jgrapht/graph/UndirectedMaskSubgraph.java | 64 - src/org/jgrapht/graph/UndirectedSubgraph.java | 106 -- .../jgrapht/graph/UndirectedWeightedSubgraph.java | 82 -- .../jgrapht/graph/UnmodifiableDirectedGraph.java | 74 -- src/org/jgrapht/graph/UnmodifiableGraph.java | 164 --- .../jgrapht/graph/UnmodifiableUndirectedGraph.java | 74 -- src/org/jgrapht/graph/WeightedMultigraph.java | 85 -- src/org/jgrapht/graph/WeightedPseudograph.java | 85 -- src/org/jgrapht/graph/package.html | 6 - src/org/jgrapht/package.html | 7 - .../jgrapht/traverse/AbstractGraphIterator.java | 217 ---- src/org/jgrapht/traverse/BreadthFirstIterator.java | 130 --- src/org/jgrapht/traverse/ClosestFirstIterator.java | 338 ------ .../jgrapht/traverse/CrossComponentIterator.java | 570 --------- src/org/jgrapht/traverse/DepthFirstIterator.java | 223 ---- src/org/jgrapht/traverse/GraphIterator.java | 114 -- .../jgrapht/traverse/TopologicalOrderIterator.java | 277 ----- src/org/jgrapht/traverse/package.html | 6 - src/org/jgrapht/util/ArrayUnenforcedSet.java | 112 -- src/org/jgrapht/util/FibonacciHeap.java | 611 ---------- src/org/jgrapht/util/FibonacciHeapNode.java | 154 --- src/org/jgrapht/util/MathUtil.java | 61 - src/org/jgrapht/util/ModifiableInteger.java | 261 ----- src/org/jgrapht/util/PrefetchIterator.java | 223 ---- src/org/jgrapht/util/TypeUtil.java | 67 -- src/org/jgrapht/util/VertexPair.java | 132 --- src/org/jgrapht/util/WeightCombiner.java | 116 -- src/org/jgrapht/util/package.html | 7 - 163 files changed, 27651 deletions(-) delete mode 100644 src/org/jgrapht/alg/AbstractPathElement.java delete mode 100644 src/org/jgrapht/alg/AbstractPathElementList.java delete mode 100644 src/org/jgrapht/alg/BellmanFordIterator.java delete mode 100644 src/org/jgrapht/alg/BellmanFordPathElement.java delete mode 100644 src/org/jgrapht/alg/BellmanFordShortestPath.java delete mode 100644 src/org/jgrapht/alg/BiconnectivityInspector.java delete mode 100644 src/org/jgrapht/alg/BlockCutpointGraph.java delete mode 100644 src/org/jgrapht/alg/BronKerboschCliqueFinder.java delete mode 100644 src/org/jgrapht/alg/ChromaticNumber.java delete mode 100644 src/org/jgrapht/alg/ConnectivityInspector.java delete mode 100644 src/org/jgrapht/alg/CycleDetector.java delete mode 100644 src/org/jgrapht/alg/DijkstraShortestPath.java delete mode 100644 src/org/jgrapht/alg/DirectedNeighborIndex.java delete mode 100644 src/org/jgrapht/alg/EdmondsBlossomShrinking.java delete mode 100644 src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java delete mode 100644 src/org/jgrapht/alg/EulerianCircuit.java delete mode 100644 src/org/jgrapht/alg/FloydWarshallShortestPaths.java delete mode 100644 src/org/jgrapht/alg/HamiltonianCycle.java delete mode 100644 src/org/jgrapht/alg/KShortestPaths.java delete mode 100644 src/org/jgrapht/alg/KShortestPathsIterator.java delete mode 100644 src/org/jgrapht/alg/KruskalMinimumSpanningTree.java delete mode 100644 src/org/jgrapht/alg/NeighborIndex.java delete mode 100644 src/org/jgrapht/alg/RankingPathElement.java delete mode 100644 src/org/jgrapht/alg/RankingPathElementList.java delete mode 100644 src/org/jgrapht/alg/StoerWagnerMinimumCut.java delete mode 100644 src/org/jgrapht/alg/StrongConnectivityInspector.java delete mode 100644 src/org/jgrapht/alg/TransitiveClosure.java delete mode 100644 src/org/jgrapht/alg/VertexCovers.java delete mode 100644 src/org/jgrapht/alg/package.html delete mode 100644 src/org/jgrapht/alg/util/UnionFind.java delete mode 100644 src/org/jgrapht/alg/util/VertexDegreeComparator.java delete mode 100644 src/org/jgrapht/alg/util/package.html delete mode 100644 src/org/jgrapht/event/ConnectedComponentTraversalEvent.java delete mode 100644 src/org/jgrapht/event/EdgeTraversalEvent.java delete mode 100644 src/org/jgrapht/event/GraphChangeEvent.java delete mode 100644 src/org/jgrapht/event/GraphEdgeChangeEvent.java delete mode 100644 src/org/jgrapht/event/GraphListener.java delete mode 100644 src/org/jgrapht/event/GraphVertexChangeEvent.java delete mode 100644 src/org/jgrapht/event/TraversalListener.java delete mode 100644 src/org/jgrapht/event/TraversalListenerAdapter.java delete mode 100644 src/org/jgrapht/event/VertexSetListener.java delete mode 100644 src/org/jgrapht/event/VertexTraversalEvent.java delete mode 100644 src/org/jgrapht/event/package.html delete mode 100644 src/org/jgrapht/experimental/GraphReader.java delete mode 100644 src/org/jgrapht/experimental/GraphSquare.java delete mode 100644 src/org/jgrapht/experimental/GraphTests.java delete mode 100644 src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java delete mode 100644 src/org/jgrapht/experimental/RandomGraphHelper.java delete mode 100644 src/org/jgrapht/experimental/UniformRandomGraphGenerator.java delete mode 100644 src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java delete mode 100644 src/org/jgrapht/experimental/alg/ExactAlgorithm.java delete mode 100644 src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java delete mode 100644 src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java delete mode 100644 src/org/jgrapht/experimental/alg/color/GreedyColoring.java delete mode 100644 src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java delete mode 100644 src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java delete mode 100644 src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java delete mode 100644 src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java delete mode 100644 src/org/jgrapht/experimental/equivalence/EquivalenceSet.java delete mode 100644 src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java delete mode 100644 src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java delete mode 100644 src/org/jgrapht/experimental/equivalence/package.html delete mode 100644 src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/GraphOrdering.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java delete mode 100644 src/org/jgrapht/experimental/isomorphism/package.html delete mode 100644 src/org/jgrapht/experimental/package.html delete mode 100644 src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java delete mode 100644 src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java delete mode 100644 src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java delete mode 100644 src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java delete mode 100644 src/org/jgrapht/experimental/permutation/PermutationFactory.java delete mode 100644 src/org/jgrapht/experimental/permutation/package.html delete mode 100644 src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java delete mode 100755 src/org/jgrapht/generate/CompleteGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/EmptyGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/GraphGenerator.java delete mode 100644 src/org/jgrapht/generate/GridGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/HyperCubeGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/LinearGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/RandomGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/RingGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/ScaleFreeGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/StarGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/WheelGraphGenerator.java delete mode 100644 src/org/jgrapht/generate/package.html delete mode 100644 src/org/jgrapht/graph/AbstractBaseGraph.java delete mode 100644 src/org/jgrapht/graph/AbstractGraph.java delete mode 100644 src/org/jgrapht/graph/AsUndirectedGraph.java delete mode 100644 src/org/jgrapht/graph/AsUnweightedDirectedGraph.java delete mode 100644 src/org/jgrapht/graph/AsUnweightedGraph.java delete mode 100644 src/org/jgrapht/graph/AsWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/ClassBasedEdgeFactory.java delete mode 100644 src/org/jgrapht/graph/ClassBasedVertexFactory.java delete mode 100644 src/org/jgrapht/graph/DefaultDirectedGraph.java delete mode 100644 src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/DefaultEdge.java delete mode 100644 src/org/jgrapht/graph/DefaultGraphMapping.java delete mode 100644 src/org/jgrapht/graph/DefaultListenableGraph.java delete mode 100644 src/org/jgrapht/graph/DefaultWeightedEdge.java delete mode 100644 src/org/jgrapht/graph/DirectedGraphUnion.java delete mode 100644 src/org/jgrapht/graph/DirectedMaskSubgraph.java delete mode 100644 src/org/jgrapht/graph/DirectedMultigraph.java delete mode 100644 src/org/jgrapht/graph/DirectedPseudograph.java delete mode 100644 src/org/jgrapht/graph/DirectedSubgraph.java delete mode 100644 src/org/jgrapht/graph/DirectedWeightedMultigraph.java delete mode 100644 src/org/jgrapht/graph/DirectedWeightedSubgraph.java delete mode 100644 src/org/jgrapht/graph/EdgeReversedGraph.java delete mode 100644 src/org/jgrapht/graph/EdgeSetFactory.java delete mode 100644 src/org/jgrapht/graph/GraphDelegator.java delete mode 100644 src/org/jgrapht/graph/GraphPathImpl.java delete mode 100644 src/org/jgrapht/graph/GraphUnion.java delete mode 100644 src/org/jgrapht/graph/IntrusiveEdge.java delete mode 100644 src/org/jgrapht/graph/ListenableDirectedGraph.java delete mode 100644 src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/ListenableUndirectedGraph.java delete mode 100644 src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/MaskEdgeSet.java delete mode 100644 src/org/jgrapht/graph/MaskFunctor.java delete mode 100644 src/org/jgrapht/graph/MaskSubgraph.java delete mode 100644 src/org/jgrapht/graph/MaskVertexSet.java delete mode 100644 src/org/jgrapht/graph/Multigraph.java delete mode 100644 src/org/jgrapht/graph/ParanoidGraph.java delete mode 100644 src/org/jgrapht/graph/Pseudograph.java delete mode 100644 src/org/jgrapht/graph/SimpleDirectedGraph.java delete mode 100644 src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/SimpleGraph.java delete mode 100644 src/org/jgrapht/graph/SimpleWeightedGraph.java delete mode 100644 src/org/jgrapht/graph/Subgraph.java delete mode 100644 src/org/jgrapht/graph/UndirectedGraphUnion.java delete mode 100644 src/org/jgrapht/graph/UndirectedMaskSubgraph.java delete mode 100644 src/org/jgrapht/graph/UndirectedSubgraph.java delete mode 100644 src/org/jgrapht/graph/UndirectedWeightedSubgraph.java delete mode 100644 src/org/jgrapht/graph/UnmodifiableDirectedGraph.java delete mode 100644 src/org/jgrapht/graph/UnmodifiableGraph.java delete mode 100644 src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java delete mode 100644 src/org/jgrapht/graph/WeightedMultigraph.java delete mode 100644 src/org/jgrapht/graph/WeightedPseudograph.java delete mode 100644 src/org/jgrapht/graph/package.html delete mode 100644 src/org/jgrapht/package.html delete mode 100644 src/org/jgrapht/traverse/AbstractGraphIterator.java delete mode 100644 src/org/jgrapht/traverse/BreadthFirstIterator.java delete mode 100644 src/org/jgrapht/traverse/ClosestFirstIterator.java delete mode 100644 src/org/jgrapht/traverse/CrossComponentIterator.java delete mode 100644 src/org/jgrapht/traverse/DepthFirstIterator.java delete mode 100644 src/org/jgrapht/traverse/GraphIterator.java delete mode 100644 src/org/jgrapht/traverse/TopologicalOrderIterator.java delete mode 100644 src/org/jgrapht/traverse/package.html delete mode 100644 src/org/jgrapht/util/ArrayUnenforcedSet.java delete mode 100644 src/org/jgrapht/util/FibonacciHeap.java delete mode 100644 src/org/jgrapht/util/FibonacciHeapNode.java delete mode 100644 src/org/jgrapht/util/MathUtil.java delete mode 100644 src/org/jgrapht/util/ModifiableInteger.java delete mode 100644 src/org/jgrapht/util/PrefetchIterator.java delete mode 100644 src/org/jgrapht/util/TypeUtil.java delete mode 100644 src/org/jgrapht/util/VertexPair.java delete mode 100644 src/org/jgrapht/util/WeightCombiner.java delete mode 100644 src/org/jgrapht/util/package.html diff --git a/src/org/jgrapht/alg/AbstractPathElement.java b/src/org/jgrapht/alg/AbstractPathElement.java deleted file mode 100644 index 5999888..0000000 --- a/src/org/jgrapht/alg/AbstractPathElement.java +++ /dev/null @@ -1,202 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * AbstractPathElement.java - * ------------------------- - * (C) Copyright 2006-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jan-2006 : Initial revision (GB); - * 14-Jan-2006 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * A new path is created from a path concatenated to an edge. It's like a linked - * list.
      - * The empty path is composed only of one vertex.
      - * In this case the path has no previous path element.
      - * . - * - *

        - *
      • Definition 4.5 Let G(V; E) be a connected undirected graph. The - * block-cut point graph (BC graph) of G, denoted by GB(VB; EB), is the - * bipartite graph defined as follows. (a) VB has one node corresponding to each - * block and one node corresponding to each cut point of G. (b) Each edge fx; yg - * in EB joins a block node x to a cut point y if the block corresponding to x - * contains the cut point node corresponding to y.
      • - *
      • Lemma 4.4 Let G(V; E) be a connected undirected graph. (a) Each - * pair of blocks of G share at most one node, and that node is a cutpoint. (b) - * The BC graph of G is a tree in which each leaf node corresponds to a block of - * G.
      • - *
      - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class BlockCutpointGraph - extends SimpleGraph, DefaultEdge> -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = -9101341117013163934L; - - //~ Instance fields -------------------------------------------------------- - - private Set cutpoints = new HashSet(); - - /** - * DFS (Depth-First-Search) tree. - */ - private DirectedGraph dfsTree; - - private UndirectedGraph graph; - - private int numOrder; - - private Deque stack = new ArrayDeque(); - - private Map>> vertex2biconnectedSubgraphs = - new HashMap>>(); - - private Map> vertex2block = - new HashMap>(); - - private Map vertex2numOrder = new HashMap(); - - //~ Constructors ----------------------------------------------------------- - - /** - * Running time = O(m) where m is the number of edges. - */ - public BlockCutpointGraph(UndirectedGraph graph) - { - super(DefaultEdge.class); - this.graph = graph; - - this.dfsTree = - new SimpleDirectedGraph( - DefaultEdge.class); - V s = graph.vertexSet().iterator().next(); - this.dfsTree.addVertex(s); - dfsVisit(s, s); - - if (this.dfsTree.edgesOf(s).size() > 1) { - this.cutpoints.add(s); - } else { - this.cutpoints.remove(s); - } - - for (Iterator iter = this.cutpoints.iterator(); iter.hasNext();) { - V cutpoint = iter.next(); - UndirectedGraph subgraph = - new SimpleGraph(this.graph.getEdgeFactory()); - subgraph.addVertex(cutpoint); - this.vertex2block.put(cutpoint, subgraph); - addVertex(subgraph); - Set> biconnectedSubgraphs = - getBiconnectedSubgraphs(cutpoint); - for ( - Iterator> iterator = - biconnectedSubgraphs.iterator(); - iterator.hasNext();) - { - UndirectedGraph biconnectedSubgraph = iterator.next(); - assert (vertexSet().contains(biconnectedSubgraph)); - addEdge(subgraph, biconnectedSubgraph); - } - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the vertex if vertex is a cutpoint, and otherwise returns the - * block (biconnected component) containing the vertex. - * - * @param vertex vertex in the initial graph. - */ - public UndirectedGraph getBlock(V vertex) - { - if (!this.graph.vertexSet().contains(vertex)) { - throw new IllegalArgumentException("No such vertex in the graph!"); - } - - return this.vertex2block.get(vertex); - } - - /** - * Returns the cutpoints of the initial graph. - */ - public Set getCutpoints() - { - return this.cutpoints; - } - - /** - * Returns true if the vertex is a cutpoint, false - * otherwise. - * - * @param vertex vertex in the initial graph. - */ - public boolean isCutpoint(V vertex) - { - if (!this.graph.vertexSet().contains(vertex)) { - throw new IllegalArgumentException("No such vertex in the graph!"); - } - - return this.cutpoints.contains(vertex); - } - - private void biconnectedComponentFinished(V s, V n) - { - this.cutpoints.add(s); - - Set vertexComponent = new HashSet(); - Set edgeComponent = new HashSet(); - BCGEdge edge = this.stack.removeLast(); - while ( - (getNumOrder(edge.getSource()) >= getNumOrder(n)) - && !this.stack.isEmpty()) - { - edgeComponent.add(edge); - - vertexComponent.add(edge.getSource()); - vertexComponent.add(edge.getTarget()); - - edge = this.stack.removeLast(); - } - edgeComponent.add(edge); - // edgeComponent is an equivalence class. - - vertexComponent.add(edge.getSource()); - vertexComponent.add(edge.getTarget()); - - VertexComponentForbiddenFunction mask = - new VertexComponentForbiddenFunction( - vertexComponent); - UndirectedGraph biconnectedSubgraph = - new UndirectedMaskSubgraph( - this.graph, - mask); - for (Iterator iter = vertexComponent.iterator(); iter.hasNext();) { - V vertex = iter.next(); - this.vertex2block.put(vertex, biconnectedSubgraph); - getBiconnectedSubgraphs(vertex).add(biconnectedSubgraph); - } - addVertex(biconnectedSubgraph); - } - - private int dfsVisit(V s, V father) - { - this.numOrder++; - int minS = this.numOrder; - setNumOrder(s, this.numOrder); - - for ( - Iterator iter = this.graph.edgesOf(s).iterator(); - iter.hasNext();) - { - E edge = iter.next(); - V n = Graphs.getOppositeVertex(this.graph, edge, s); - if (getNumOrder(n) == 0) { - this.dfsTree.addVertex(n); - BCGEdge dfsEdge = new BCGEdge(s, n); - this.dfsTree.addEdge(s, n, dfsEdge); - - this.stack.add(dfsEdge); - - // minimum of the traverse orders of the "attach points" of - // the vertex n. - int minN = dfsVisit(n, s); - minS = Math.min(minN, minS); - if (minN >= getNumOrder(s)) { - // s is a cutpoint. - // it has a son whose "attach depth" is greater or equal. - biconnectedComponentFinished(s, n); - } - } else if ((getNumOrder(n) < getNumOrder(s)) && !n.equals(father)) { - BCGEdge backwardEdge = new BCGEdge(s, n); - this.stack.add(backwardEdge); - - // n is an "attach point" of s. {s->n} is a backward edge. - minS = Math.min(getNumOrder(n), minS); - } - } - - // minimum of the traverse orders of the "attach points" of - // the vertex s. - return minS; - } - - /** - * Returns the biconnected components containing the vertex. A vertex which - * is not a cutpoint is contained in exactly one component. A cutpoint is - * contained is at least 2 components. - * - * @param vertex vertex in the initial graph. - */ - private Set> getBiconnectedSubgraphs(V vertex) - { - Set> biconnectedSubgraphs = - this.vertex2biconnectedSubgraphs.get(vertex); - if (biconnectedSubgraphs == null) { - biconnectedSubgraphs = new HashSet>(); - this.vertex2biconnectedSubgraphs.put(vertex, biconnectedSubgraphs); - } - return biconnectedSubgraphs; - } - - /** - * Returns the traverse order of the vertex in the DFS. - */ - private int getNumOrder(V vertex) - { - assert (vertex != null); - - Integer numOrder = this.vertex2numOrder.get(vertex); - if (numOrder == null) { - return 0; - } else { - return numOrder.intValue(); - } - } - - private void setNumOrder(V vertex, int numOrder) - { - this.vertex2numOrder.put(vertex, Integer.valueOf(numOrder)); - } - - //~ Inner Classes ---------------------------------------------------------- - - private class BCGEdge - extends DefaultEdge - { - /** - */ - private static final long serialVersionUID = -5115006161815760059L; - - private V source; - - private V target; - - public BCGEdge(V source, V target) - { - super(); - this.source = source; - this.target = target; - } - - public V getSource() - { - return this.source; - } - - public V getTarget() - { - return this.target; - } - } - - private class VertexComponentForbiddenFunction - implements MaskFunctor - { - private Set vertexComponent; - - public VertexComponentForbiddenFunction(Set vertexComponent) - { - this.vertexComponent = vertexComponent; - } - - public boolean isEdgeMasked(E edge) - { - return false; - } - - public boolean isVertexMasked(V vertex) - { - if (this.vertexComponent.contains(vertex)) { - // vertex belongs to component then we do not mask it. - return false; - } else { - return true; - } - } - } -} - -// End BlockCutpointGraph.java diff --git a/src/org/jgrapht/alg/BronKerboschCliqueFinder.java b/src/org/jgrapht/alg/BronKerboschCliqueFinder.java deleted file mode 100644 index bcce728..0000000 --- a/src/org/jgrapht/alg/BronKerboschCliqueFinder.java +++ /dev/null @@ -1,198 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * BronKerboschCliqueFinder.java - * ------------------- - * (C) Copyright 2005-2008, by Ewgenij Proschak and Contributors. - * - * Original Author: Ewgenij Proschak - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 21-Jul-2005 : Initial revision (EP); - * 26-Jul-2005 : Cleaned up and checked in (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * This class implements Bron-Kerbosch clique detection algorithm as it is - * described in [Samudrala R.,Moult J.:A Graph-theoretic Algorithm for - * comparative Modeling of Protein Structure; J.Mol. Biol. (1998); vol 279; pp. - * 287-302] - * - * @author Ewgenij Proschak - */ -public class BronKerboschCliqueFinder -{ - //~ Instance fields -------------------------------------------------------- - - private final Graph graph; - - private Collection> cliques; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new clique finder. - * - * @param graph the graph in which cliques are to be found; graph must be - * simple - */ - public BronKerboschCliqueFinder(Graph graph) - { - this.graph = graph; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Finds all maximal cliques of the graph. A clique is maximal if it is - * impossible to enlarge it by adding another vertex from the graph. Note - * that a maximal clique is not necessarily the biggest clique in the graph. - * - * @return Collection of cliques (each of which is represented as a Set of - * vertices) - */ - public Collection> getAllMaximalCliques() - { - // TODO jvs 26-July-2005: assert that graph is simple - - cliques = new ArrayList>(); - List potential_clique = new ArrayList(); - List candidates = new ArrayList(); - List already_found = new ArrayList(); - candidates.addAll(graph.vertexSet()); - findCliques(potential_clique, candidates, already_found); - return cliques; - } - - /** - * Finds the biggest maximal cliques of the graph. - * - * @return Collection of cliques (each of which is represented as a Set of - * vertices) - */ - public Collection> getBiggestMaximalCliques() - { - // first, find all cliques - getAllMaximalCliques(); - - int maximum = 0; - Collection> biggest_cliques = new ArrayList>(); - for (Set clique : cliques) { - if (maximum < clique.size()) { - maximum = clique.size(); - } - } - for (Set clique : cliques) { - if (maximum == clique.size()) { - biggest_cliques.add(clique); - } - } - return biggest_cliques; - } - - private void findCliques( - List potential_clique, - List candidates, - List already_found) - { - List candidates_array = new ArrayList(candidates); - if (!end(candidates, already_found)) { - // for each candidate_node in candidates do - for (V candidate : candidates_array) { - List new_candidates = new ArrayList(); - List new_already_found = new ArrayList(); - - // move candidate node to potential_clique - potential_clique.add(candidate); - candidates.remove(candidate); - - // create new_candidates by removing nodes in candidates not - // connected to candidate node - for (V new_candidate : candidates) { - if (graph.containsEdge(candidate, new_candidate)) { - new_candidates.add(new_candidate); - } // of if - } // of for - - // create new_already_found by removing nodes in already_found - // not connected to candidate node - for (V new_found : already_found) { - if (graph.containsEdge(candidate, new_found)) { - new_already_found.add(new_found); - } // of if - } // of for - - // if new_candidates and new_already_found are empty - if (new_candidates.isEmpty() && new_already_found.isEmpty()) { - // potential_clique is maximal_clique - cliques.add(new HashSet(potential_clique)); - } // of if - else { - // recursive call - findCliques( - potential_clique, - new_candidates, - new_already_found); - } // of else - - // move candidate_node from potential_clique to already_found; - already_found.add(candidate); - potential_clique.remove(candidate); - } // of for - } // of if - } - - private boolean end(List candidates, List already_found) - { - // if a node in already_found is connected to all nodes in candidates - boolean end = false; - int edgecounter; - for (V found : already_found) { - edgecounter = 0; - for (V candidate : candidates) { - if (graph.containsEdge(found, candidate)) { - edgecounter++; - } // of if - } // of for - if (edgecounter == candidates.size()) { - end = true; - } - } // of for - return end; - } -} - -// End BronKerboschCliqueFinder.java diff --git a/src/org/jgrapht/alg/ChromaticNumber.java b/src/org/jgrapht/alg/ChromaticNumber.java deleted file mode 100644 index 84a7329..0000000 --- a/src/org/jgrapht/alg/ChromaticNumber.java +++ /dev/null @@ -1,147 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * ChromaticNumber.java - * ------------------- - * (C) Copyright 2008-2008, by Andrew Newell and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): gpaschos@netscape.net, harshalv@telenav.com - * - * $Id$ - * - * Changes - * ------- - * 24-Dec-2008 : Initial revision (AN); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.alg.util.*; -import org.jgrapht.graph.*; - - -/** - * Allows the - * chromatic number of a graph to be calculated. This is the minimal number - * of colors needed to color each vertex such that no two adjacent vertices - * share the same color. This algorithm will not find the true chromatic number, - * since this is an NP-complete problem. So, a greedy algorithm will find an - * approximate chromatic number. - * - * @author Andrew Newell - * @since Dec 21, 2008 - */ -public abstract class ChromaticNumber -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Finds the number of colors required for a greedy coloring of the graph. - * - * @param g an undirected graph to find the chromatic number of - * - * @return integer the approximate chromatic number from the greedy - * algorithm - */ - public static int findGreedyChromaticNumber(UndirectedGraph g) - { - Map> coloredGroups = findGreedyColoredGroups(g); - return coloredGroups.keySet().size(); - } - - /** - * Finds a greedy coloring of the graph. - * - * @param g an undirected graph for which to find the coloring - */ - public static Map> findGreedyColoredGroups( - UndirectedGraph g) - { - // A copy of the graph is made, so that elements of the graph may be - // removed to carry out the algorithm - UndirectedGraph sg = new UndirectedSubgraph(g, null, null); - - // The Vertices will be sorted in decreasing order by degree, so that - // higher degree vertices have priority to be colored first - VertexDegreeComparator comp = - new VertexDegreeComparator(sg); - List sortedVertices = new LinkedList(sg.vertexSet()); - Collections.sort(sortedVertices, comp); - Collections.reverse(sortedVertices); - - int color; - - // create a map which will hold color as key and Set as value - Map> coloredGroups = new HashMap>(); - - // We'll attempt to color each vertex with a single color each - // iteration, and these vertices will be removed from the graph at the - // end of each iteration - for (color = 0; sg.vertexSet().size() > 0; color++) { - // This set will contain vertices that are colored with the - // current color of this iteration - Set currentColor = new HashSet(); - for ( - Iterator iter = sortedVertices.iterator(); - iter.hasNext();) - { - V v = iter.next(); - - // Add new vertices to be colored as long as they are not - // adjacent with any other vertex that has already been colored - // with the current color - boolean flag = true; - for ( - Iterator innerIter = currentColor.iterator(); - innerIter.hasNext();) - { - V temp = innerIter.next(); - if (sg.containsEdge(temp, v)) { - flag = false; - break; - } - } - if (flag) { - currentColor.add(v); - iter.remove(); - } - } - - // Add all these vertices as a group for this color - coloredGroups.put(color, currentColor); - - // Remove vertices from the graph and then repeat the process for - // the next iteration - sg.removeAllVertices(currentColor); - } - return coloredGroups; - } -} - -// End ChromaticNumber.java diff --git a/src/org/jgrapht/alg/ConnectivityInspector.java b/src/org/jgrapht/alg/ConnectivityInspector.java deleted file mode 100644 index d242878..0000000 --- a/src/org/jgrapht/alg/ConnectivityInspector.java +++ /dev/null @@ -1,302 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * ConnectivityInspector.java - * -------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): John V. Sichi - * Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 06-Aug-2003 : Initial revision (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 07-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; -import org.jgrapht.graph.*; -import org.jgrapht.traverse.*; - - -/** - * Allows obtaining various connectivity aspects of a graph. The inspected - * graph is specified at construction time and cannot be modified. - * Currently, the inspector supports connected components for an undirected - * graph and weakly connected components for a directed graph. To find strongly - * connected components, use {@link StrongConnectivityInspector} instead. - * - *

      The inspector methods work in a lazy fashion: no computation is performed - * unless immediately necessary. Computation are done once and results and - * cached within this class for future need.

      - * - *

      The inspector is also a {@link org.jgrapht.event.GraphListener}. If added - * as a listener to the inspected graph, the inspector will amend internal - * cached results instead of recomputing them. It is efficient when a few - * modifications are applied to a large graph. If many modifications are - * expected it will not be efficient due to added overhead on graph update - * operations. If inspector is added as listener to a graph other than the one - * it inspects, results are undefined.

      - * - * @author Barak Naveh - * @author John V. Sichi - * @since Aug 6, 2003 - */ -public class ConnectivityInspector - implements GraphListener -{ - //~ Instance fields -------------------------------------------------------- - - List> connectedSets; - Map> vertexToConnectedSet; - private Graph graph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a connectivity inspector for the specified undirected graph. - * - * @param g the graph for which a connectivity inspector to be created. - */ - public ConnectivityInspector(UndirectedGraph g) - { - init(); - this.graph = g; - } - - /** - * Creates a connectivity inspector for the specified directed graph. - * - * @param g the graph for which a connectivity inspector to be created. - */ - public ConnectivityInspector(DirectedGraph g) - { - init(); - this.graph = new AsUndirectedGraph(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Test if the inspected graph is connected. An empty graph is not - * considered connected. - * - * @return true if and only if inspected graph is connected. - */ - public boolean isGraphConnected() - { - return lazyFindConnectedSets().size() == 1; - } - - /** - * Returns a set of all vertices that are in the maximally connected - * component together with the specified vertex. For more on maximally - * connected component, see - * http://www.nist.gov/dads/HTML/maximallyConnectedComponent.html. - * - * @param vertex the vertex for which the connected set to be returned. - * - * @return a set of all vertices that are in the maximally connected - * component together with the specified vertex. - */ - public Set connectedSetOf(V vertex) - { - Set connectedSet = vertexToConnectedSet.get(vertex); - - if (connectedSet == null) { - connectedSet = new HashSet(); - - BreadthFirstIterator i = - new BreadthFirstIterator(graph, vertex); - - while (i.hasNext()) { - connectedSet.add(i.next()); - } - - vertexToConnectedSet.put(vertex, connectedSet); - } - - return connectedSet; - } - - /** - * Returns a list of Set s, where each set contains all - * vertices that are in the same maximally connected component. All graph - * vertices occur in exactly one set. For more on maximally connected - * component, see - * http://www.nist.gov/dads/HTML/maximallyConnectedComponent.html. - * - * @return Returns a list of Set s, where each set contains all - * vertices that are in the same maximally connected component. - */ - public List> connectedSets() - { - return lazyFindConnectedSets(); - } - - /** - * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) - */ - public void edgeAdded(GraphEdgeChangeEvent e) - { - init(); // for now invalidate cached results, in the future need to - // amend them. - } - - /** - * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) - */ - public void edgeRemoved(GraphEdgeChangeEvent e) - { - init(); // for now invalidate cached results, in the future need to - // amend them. - } - - /** - * Tests if there is a path from the specified source vertex to the - * specified target vertices. For a directed graph, direction is ignored for - * this interpretation of path. - * - *

      Note: Future versions of this method might not ignore edge directions - * for directed graphs.

      - * - * @param sourceVertex one end of the path. - * @param targetVertex another end of the path. - * - * @return true if and only if there is a path from the source - * vertex to the target vertex. - */ - public boolean pathExists(V sourceVertex, V targetVertex) - { - /* - * TODO: Ignoring edge direction for directed graph may be - * confusing. For directed graphs, consider Dijkstra's algorithm. - */ - Set sourceSet = connectedSetOf(sourceVertex); - - return sourceSet.contains(targetVertex); - } - - /** - * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) - */ - public void vertexAdded(GraphVertexChangeEvent e) - { - init(); // for now invalidate cached results, in the future need to - // amend them. - } - - /** - * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) - */ - public void vertexRemoved(GraphVertexChangeEvent e) - { - init(); // for now invalidate cached results, in the future need to - // amend them. - } - - private void init() - { - connectedSets = null; - vertexToConnectedSet = new HashMap>(); - } - - private List> lazyFindConnectedSets() - { - if (connectedSets == null) { - connectedSets = new ArrayList>(); - - Set vertexSet = graph.vertexSet(); - - if (vertexSet.size() > 0) { - BreadthFirstIterator i = - new BreadthFirstIterator(graph, null); - i.addTraversalListener(new MyTraversalListener()); - - while (i.hasNext()) { - i.next(); - } - } - } - - return connectedSets; - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * A traversal listener that groups all vertices according to to their - * containing connected set. - * - * @author Barak Naveh - * @since Aug 6, 2003 - */ - private class MyTraversalListener - extends TraversalListenerAdapter - { - private Set currentConnectedSet; - - /** - * @see TraversalListenerAdapter#connectedComponentFinished(ConnectedComponentTraversalEvent) - */ - public void connectedComponentFinished( - ConnectedComponentTraversalEvent e) - { - connectedSets.add(currentConnectedSet); - } - - /** - * @see TraversalListenerAdapter#connectedComponentStarted(ConnectedComponentTraversalEvent) - */ - public void connectedComponentStarted( - ConnectedComponentTraversalEvent e) - { - currentConnectedSet = new HashSet(); - } - - /** - * @see TraversalListenerAdapter#vertexTraversed(VertexTraversalEvent) - */ - public void vertexTraversed(VertexTraversalEvent e) - { - V v = e.getVertex(); - currentConnectedSet.add(v); - vertexToConnectedSet.put(v, currentConnectedSet); - } - } -} - -// End ConnectivityInspector.java diff --git a/src/org/jgrapht/alg/CycleDetector.java b/src/org/jgrapht/alg/CycleDetector.java deleted file mode 100644 index 3cd1a60..0000000 --- a/src/org/jgrapht/alg/CycleDetector.java +++ /dev/null @@ -1,271 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * CycleDetector.java - * ------------------ - * (C) Copyright 2004-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 16-Sept-2004 : Initial revision (JVS); - * 07-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.traverse.*; - - -/** - * Performs cycle detection on a graph. The inspected graph is specified - * at construction time and cannot be modified. Currently, the detector supports - * only directed graphs. - * - * @author John V. Sichi - * @since Sept 16, 2004 - */ -public class CycleDetector -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Graph on which cycle detection is being performed. - */ - DirectedGraph graph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a cycle detector for the specified graph. Currently only directed - * graphs are supported. - * - * @param graph the DirectedGraph in which to detect cycles - */ - public CycleDetector(DirectedGraph graph) - { - this.graph = graph; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Performs yes/no cycle detection on the entire graph. - * - * @return true iff the graph contains at least one cycle - */ - public boolean detectCycles() - { - try { - execute(null, null); - } catch (CycleDetectedException ex) { - return true; - } - - return false; - } - - /** - * Performs yes/no cycle detection on an individual vertex. - * - * @param v the vertex to test - * - * @return true if v is on at least one cycle - */ - public boolean detectCyclesContainingVertex(V v) - { - try { - execute(null, v); - } catch (CycleDetectedException ex) { - return true; - } - - return false; - } - - /** - * Finds the vertex set for the subgraph of all cycles. - * - * @return set of all vertices which participate in at least one cycle in - * this graph - */ - public Set findCycles() - { - // ProbeIterator can't be used to handle this case, - // so use StrongConnectivityInspector instead. - StrongConnectivityInspector inspector = - new StrongConnectivityInspector(graph); - List> components = inspector.stronglyConnectedSets(); - - // A vertex participates in a cycle if either of the following is - // true: (a) it is in a component whose size is greater than 1 - // or (b) it is a self-loop - - Set set = new HashSet(); - for (Set component : components) { - if (component.size() > 1) { - // cycle - set.addAll(component); - } else { - V v = component.iterator().next(); - if (graph.containsEdge(v, v)) { - // self-loop - set.add(v); - } - } - } - - return set; - } - - /** - * Finds the vertex set for the subgraph of all cycles which contain a - * particular vertex. - * - *

      REVIEW jvs 25-Aug-2006: This implementation is not guaranteed to cover - * all cases. If you want to be absolutely certain that you report vertices - * from all cycles containing v, it's safer (but less efficient) to use - * StrongConnectivityInspector instead and return the strongly connected - * component containing v. - * - * @param v the vertex to test - * - * @return set of all vertices reachable from v via at least one cycle - */ - public Set findCyclesContainingVertex(V v) - { - Set set = new HashSet(); - execute(set, v); - - return set; - } - - private void execute(Set s, V v) - { - ProbeIterator iter = new ProbeIterator(s, v); - - while (iter.hasNext()) { - iter.next(); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Exception thrown internally when a cycle is detected during a yes/no - * cycle test. Must be caught by top-level detection method. - */ - private static class CycleDetectedException - extends RuntimeException - { - private static final long serialVersionUID = 3834305137802950712L; - } - - /** - * Version of DFS which maintains a backtracking path used to probe for - * cycles. - */ - private class ProbeIterator - extends DepthFirstIterator - { - private List path; - private Set cycleSet; - private V root; - - ProbeIterator(Set cycleSet, V startVertex) - { - super(graph, startVertex); - root = startVertex; - this.cycleSet = cycleSet; - path = new ArrayList(); - } - - /** - * {@inheritDoc} - */ - protected void encounterVertexAgain(V vertex, E edge) - { - super.encounterVertexAgain(vertex, edge); - - int i; - - if (root != null) { - // For rooted detection, the path must either - // double back to the root, or to a node of a cycle - // which has already been detected. - if (vertex.equals(root)) { - i = 0; - } else if ((cycleSet != null) && cycleSet.contains(vertex)) { - i = 0; - } else { - return; - } - } else { - i = path.indexOf(vertex); - } - - if (i > -1) { - if (cycleSet == null) { - // we're doing yes/no cycle detection - throw new CycleDetectedException(); - } else { - for (; i < path.size(); ++i) { - cycleSet.add(path.get(i)); - } - } - } - } - - /** - * {@inheritDoc} - */ - protected V provideNextVertex() - { - V v = super.provideNextVertex(); - - // backtrack - for (int i = path.size() - 1; i >= 0; --i) { - if (graph.containsEdge(path.get(i), v)) { - break; - } - - path.remove(i); - } - - path.add(v); - - return v; - } - } -} - -// End CycleDetector.java diff --git a/src/org/jgrapht/alg/DijkstraShortestPath.java b/src/org/jgrapht/alg/DijkstraShortestPath.java deleted file mode 100644 index 43a6532..0000000 --- a/src/org/jgrapht/alg/DijkstraShortestPath.java +++ /dev/null @@ -1,218 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * DijkstraShortestPath.java - * ------------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 02-Sep-2003 : Initial revision (JVS); - * 29-May-2005 : Make non-static and add radius support (JVS); - * 07-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; -import org.jgrapht.traverse.*; - - -/** - * An implementation of Dijkstra's - * shortest path algorithm using ClosestFirstIterator. - * - * @author John V. Sichi - * @since Sep 2, 2003 - */ -public final class DijkstraShortestPath -{ - //~ Instance fields -------------------------------------------------------- - - private GraphPath path; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates and executes a new DijkstraShortestPath algorithm instance. An - * instance is only good for a single search; after construction, it can be - * accessed to retrieve information about the path found. - * - * @param graph the graph to be searched - * @param startVertex the vertex at which the path should start - * @param endVertex the vertex at which the path should end - */ - public DijkstraShortestPath(Graph graph, - V startVertex, - V endVertex) - { - this(graph, startVertex, endVertex, Double.POSITIVE_INFINITY); - } - - /** - * Creates and executes a new DijkstraShortestPath algorithm instance. An - * instance is only good for a single search; after construction, it can be - * accessed to retrieve information about the path found. - * - * @param graph the graph to be searched - * @param startVertex the vertex at which the path should start - * @param endVertex the vertex at which the path should end - * @param radius limit on path length, or Double.POSITIVE_INFINITY for - * unbounded search - */ - public DijkstraShortestPath( - Graph graph, - V startVertex, - V endVertex, - double radius) - { - if (!graph.containsVertex(endVertex)) { - throw new IllegalArgumentException( - "graph must contain the end vertex"); - } - - ClosestFirstIterator iter = - new ClosestFirstIterator(graph, startVertex, radius); - - while (iter.hasNext()) { - V vertex = iter.next(); - - if (vertex.equals(endVertex)) { - createEdgeList(graph, iter, startVertex, endVertex); - return; - } - } - - path = null; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Return the edges making up the path found. - * - * @return List of Edges, or null if no path exists - */ - public List getPathEdgeList() - { - if (path == null) { - return null; - } else { - return path.getEdgeList(); - } - } - - /** - * Return the path found. - * - * @return path representation, or null if no path exists - */ - public GraphPath getPath() - { - return path; - } - - /** - * Return the length of the path found. - * - * @return path length, or Double.POSITIVE_INFINITY if no path exists - */ - public double getPathLength() - { - if (path == null) { - return Double.POSITIVE_INFINITY; - } else { - return path.getWeight(); - } - } - - /** - * Convenience method to find the shortest path via a single static method - * call. If you need a more advanced search (e.g. limited by radius, or - * computation of the path length), use the constructor instead. - * - * @param graph the graph to be searched - * @param startVertex the vertex at which the path should start - * @param endVertex the vertex at which the path should end - * - * @return List of Edges, or null if no path exists - */ - public static List findPathBetween( - Graph graph, - V startVertex, - V endVertex) - { - DijkstraShortestPath alg = - new DijkstraShortestPath( - graph, - startVertex, - endVertex); - - return alg.getPathEdgeList(); - } - - private void createEdgeList( - Graph graph, - ClosestFirstIterator iter, - V startVertex, - V endVertex) - { - List edgeList = new ArrayList(); - - V v = endVertex; - - while (true) { - E edge = iter.getSpanningTreeEdge(v); - - if (edge == null) { - break; - } - - edgeList.add(edge); - v = Graphs.getOppositeVertex(graph, edge, v); - } - - Collections.reverse(edgeList); - double pathLength = iter.getShortestPathLength(endVertex); - path = - new GraphPathImpl( - graph, - startVertex, - endVertex, - edgeList, - pathLength); - } -} - -// End DijkstraShortestPath.java diff --git a/src/org/jgrapht/alg/DirectedNeighborIndex.java b/src/org/jgrapht/alg/DirectedNeighborIndex.java deleted file mode 100644 index fdf7557..0000000 --- a/src/org/jgrapht/alg/DirectedNeighborIndex.java +++ /dev/null @@ -1,233 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * DirectedNeighborIndex.java - * -------------------------- - * (C) Copyright 2005-2008, by Charles Fry and Contributors. - * - * Original Author: Charles Fry - * - * $Id$ - * - * Changes - * ------- - * 13-Dec-2005 : Initial revision (CF); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.alg.NeighborIndex.*; -import org.jgrapht.event.*; - - -/** - * Maintains a cache of each vertex's neighbors. While lists of neighbors can be - * obtained from {@link Graphs}, they are re-calculated at each invocation by - * walking a vertex's incident edges, which becomes inordinately expensive when - * performed often. - * - *

      A vertex's neighbors are cached the first time they are asked for (i.e. - * the index is built on demand). The index will only be updated automatically - * if it is added to the associated graph as a listener. If it is added as a - * listener to a graph other than the one it indexes, results are undefined.

      - * - * @author Charles Fry - * @since Dec 13, 2005 - */ -public class DirectedNeighborIndex - implements GraphListener -{ - //~ Instance fields -------------------------------------------------------- - - Map> predecessorMap = new HashMap>(); - Map> successorMap = new HashMap>(); - private DirectedGraph graph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a neighbor index for the specified directed graph. - * - * @param g the graph for which a neighbor index is to be created. - */ - public DirectedNeighborIndex(DirectedGraph g) - { - graph = g; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the set of vertices which are the predecessors of a specified - * vertex. The returned set is backed by the index, and will be updated when - * the graph changes as long as the index has been added as a listener to - * the graph. - * - * @param v the vertex whose predecessors are desired - * - * @return all unique predecessors of the specified vertex - */ - public Set predecessorsOf(V v) - { - return getPredecessors(v).getNeighbors(); - } - - /** - * Returns the set of vertices which are the predecessors of a specified - * vertex. If the graph is a multigraph, vertices may appear more than once - * in the returned list. Because a list of predecessors can not be - * efficiently maintained, it is reconstructed on every invocation by - * duplicating entries in the neighbor set. It is thus more efficient to use - * {@link #predecessorsOf(Object)} unless duplicate neighbors are required. - * - * @param v the vertex whose predecessors are desired - * - * @return all predecessors of the specified vertex - */ - public List predecessorListOf(V v) - { - return getPredecessors(v).getNeighborList(); - } - - /** - * Returns the set of vertices which are the successors of a specified - * vertex. The returned set is backed by the index, and will be updated when - * the graph changes as long as the index has been added as a listener to - * the graph. - * - * @param v the vertex whose successors are desired - * - * @return all unique successors of the specified vertex - */ - public Set successorsOf(V v) - { - return getSuccessors(v).getNeighbors(); - } - - /** - * Returns the set of vertices which are the successors of a specified - * vertex. If the graph is a multigraph, vertices may appear more than once - * in the returned list. Because a list of successors can not be efficiently - * maintained, it is reconstructed on every invocation by duplicating - * entries in the neighbor set. It is thus more efficient to use {@link - * #successorsOf(Object)} unless duplicate neighbors are required. - * - * @param v the vertex whose successors are desired - * - * @return all successors of the specified vertex - */ - public List successorListOf(V v) - { - return getSuccessors(v).getNeighborList(); - } - - /** - * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) - */ - public void edgeAdded(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - V source = graph.getEdgeSource(edge); - V target = graph.getEdgeTarget(edge); - - // if a map does not already contain an entry, - // then skip addNeighbor, since instantiating the map - // will take care of processing the edge (which has already - // been added) - - if (successorMap.containsKey(source)) { - getSuccessors(source).addNeighbor(target); - } else { - getSuccessors(source); - } - if (predecessorMap.containsKey(target)) { - getPredecessors(target).addNeighbor(source); - } else { - getPredecessors(target); - } - } - - /** - * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) - */ - public void edgeRemoved(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - V source = e.getEdgeSource(); - V target = e.getEdgeTarget(); - if (successorMap.containsKey(source)) { - successorMap.get(source).removeNeighbor(target); - } - if (predecessorMap.containsKey(target)) { - predecessorMap.get(target).removeNeighbor(source); - } - } - - /** - * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) - */ - public void vertexAdded(GraphVertexChangeEvent e) - { - // nothing to cache until there are edges - } - - /** - * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) - */ - public void vertexRemoved(GraphVertexChangeEvent e) - { - predecessorMap.remove(e.getVertex()); - successorMap.remove(e.getVertex()); - } - - private Neighbors getPredecessors(V v) - { - Neighbors neighbors = predecessorMap.get(v); - if (neighbors == null) { - neighbors = - new Neighbors(v, - Graphs.predecessorListOf(graph, v)); - predecessorMap.put(v, neighbors); - } - return neighbors; - } - - private Neighbors getSuccessors(V v) - { - Neighbors neighbors = successorMap.get(v); - if (neighbors == null) { - neighbors = - new Neighbors(v, - Graphs.successorListOf(graph, v)); - successorMap.put(v, neighbors); - } - return neighbors; - } -} - -// End DirectedNeighborIndex.java diff --git a/src/org/jgrapht/alg/EdmondsBlossomShrinking.java b/src/org/jgrapht/alg/EdmondsBlossomShrinking.java deleted file mode 100644 index 866b4d3..0000000 --- a/src/org/jgrapht/alg/EdmondsBlossomShrinking.java +++ /dev/null @@ -1,194 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2012, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * EdmondsBlossomShrinking.java - * ------------------------- - * (C) Copyright 2012-2012, by Alejandro Ramon Lopez del Huerto and Contributors. - * - * Original Author: Alejandro Ramon Lopez del Huerto - * Contributor(s): - * - * Changes - * ------- - * 24-Jan-2012 : Initial revision (ARLH); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - -/** - * An implementation of Edmonds Blossom Shrinking algorithm for constructing - * maximum matchings on graphs. The algorithm runs in time O(V^4). - * - * @author Alejandro R. Lopez del Huerto - * @since Jan 24, 2012 - */ -public class EdmondsBlossomShrinking -{ - // ~ Instance fields - // -------------------------------------------------------- - - private Map match; - private Map p; - private Map base; - private Queue q; - private Set used; - private Set blossom; - - // ~ Methods - // ---------------------------------------------------------------- - - /** - * Runs the algorithm on the input graph and returns the match edge set. - * - * @param g - * The graph to be matched - * @return set of Edges - */ - public Set findMatch(final UndirectedGraph g) - { - Set result = new ArrayUnenforcedSet(); - match = new HashMap(); - p = new HashMap(); - q = new ArrayDeque(); - base = new HashMap(); - used = new HashSet(); - blossom = new HashSet(); - - for (V i : g.vertexSet()) { - if (!match.containsKey(i)) { - V v = findPath(g, i); - while (v != null) { - V pv = p.get(v); - V ppv = match.get(pv); - match.put(v, pv); - match.put(pv, v); - v = ppv; - } - } - } - - Set seen = new HashSet(); - for (V v : g.vertexSet()) { - if (!seen.contains(v) && match.containsKey(v)) { - seen.add(v); - seen.add(match.get(v)); - result.add(g.getEdge(v, match.get(v))); - } - } - - return result; - } - - private V findPath(UndirectedGraph g, V root) - { - used.clear(); - p.clear(); - base.clear(); - - for (V i : g.vertexSet()) { - base.put(i, i); - } - - used.add(root); - q.add(root); - while (!q.isEmpty()) { - V v = q.remove(); - for (V to : g.vertexSet()) { - if (!g.containsEdge(v, to)) { - continue; - } - - if ((base.get(v) == base.get(to)) || (match.get(v) == to)) { - continue; - } - if (to == root || (match.containsKey(to)) - && (p.containsKey(match.get(to)))) { - V curbase = lca(g, v, to); - blossom.clear(); - markPath(g, v, curbase, to); - markPath(g, to, curbase, v); - - for (V i : g.vertexSet()) { - if (base.containsKey(i) - && blossom.contains(base.get(i))) - { - base.put(i, curbase); - if (!used.contains(i)) { - used.add(i); - q.add(i); - } - } - } - } else if (!p.containsKey(to)) { - p.put(to, v); - if (!match.containsKey(to)) { - return to; - } - to = match.get(to); - used.add(to); - q.add(to); - } - } - } - return null; - } - - private void markPath(UndirectedGraph g, V v, V b, V children) - { - while (base.get(v) != b) { - blossom.add(base.get(v)); - blossom.add(base.get(match.get(v))); - p.put(v, children); - children = match.get(v); - v = p.get(match.get(v)); - } - } - - private V lca(UndirectedGraph g, V a, V b) - { - Set seen = new HashSet(); - for (;;) { - a = base.get(a); - seen.add(a); - if (!match.containsKey(a)) { - break; - } - a = p.get(match.get(a)); - } - for (;;) { - b = base.get(b); - if (seen.contains(b)) { - return b; - } - b = p.get(match.get(b)); - } - } - -} diff --git a/src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java b/src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java deleted file mode 100644 index 85d80d1..0000000 --- a/src/org/jgrapht/alg/EdmondsKarpMaximumFlow.java +++ /dev/null @@ -1,361 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EdmondsKarpMaximumFlow.java - * ----------------- - * (C) Copyright 2008-2008, by Ilya Razenshteyn and Contributors. - * - * Original Author: Ilya Razenshteyn - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * A flow network is a - * directed graph where each edge has a capacity and each edge receives a flow. - * The amount of flow on an edge can not exceed the capacity of the edge (note, - * that all capacities must be non-negative). A flow must satisfy the - * restriction that the amount of flow into a vertex equals the amount of flow - * out of it, except when it is a source, which "produces" flow, or sink, which - * "consumes" flow. - * - *

      This class computes maximum flow in a network using Edmonds-Karp - * algorithm. Be careful: for large networks this algorithm may consume - * significant amount of time (its upper-bound complexity is O(VE^2), where V - - * amount of vertices, E - amount of edges in the network). - * - *

      For more details see Andrew V. Goldberg's Combinatorial Optimization - * (Lecture Notes). - */ -public final class EdmondsKarpMaximumFlow -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Default tolerance. - */ - public static final double DEFAULT_EPSILON = 0.000000001; - - //~ Instance fields -------------------------------------------------------- - - private DirectedGraph network; // our network - private double epsilon; // tolerance (DEFAULT_EPSILON or user-defined) - private int currentSource; // current source vertex - private int currentSink; // current sink vertex - private Map maximumFlow; // current maximum flow - private Double maximumFlowValue; // current maximum flow value - private int numNodes; // number of nodes in the network - private Map indexer; // mapping from vertices to their indexes - // in the internal representation - private List nodes; // internal representation of the network - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructs MaximumFlow instance to work with a copy of - * network. Current source and sink are set to null. If - * network is weighted, then capacities are weights, otherwise all - * capacities are equal to one. Doubles are compared using - * DEFAULT_EPSILON tolerance. - * - * @param network network, where maximum flow will be calculated - */ - public EdmondsKarpMaximumFlow(DirectedGraph network) - { - this(network, DEFAULT_EPSILON); - } - - /** - * Constructs MaximumFlow instance to work with a copy of - * network. Current source and sink are set to null. If - * network is weighted, then capacities are weights, otherwise all - * capacities are equal to one. - * - * @param network network, where maximum flow will be calculated - * @param epsilon tolerance for comparing doubles - */ - public EdmondsKarpMaximumFlow(DirectedGraph network, - double epsilon) - { - if (network == null) { - throw new NullPointerException("network is null"); - } - if (epsilon <= 0) { - throw new IllegalArgumentException( - "invalid epsilon (must be positive)"); - } - for (E e : network.edgeSet()) { - if (network.getEdgeWeight(e) < -epsilon) { - throw new IllegalArgumentException( - "invalid capacity (must be non-negative)"); - } - } - - this.network = network; - this.epsilon = epsilon; - - currentSource = -1; - currentSink = -1; - maximumFlow = null; - maximumFlowValue = null; - - buildInternalNetwork(); - } - - //~ Methods ---------------------------------------------------------------- - - // converting the original network into internal more convenient format - private void buildInternalNetwork() - { - numNodes = network.vertexSet().size(); - nodes = new ArrayList(); - Iterator it = network.vertexSet().iterator(); - indexer = new HashMap(); - for (int i = 0; i < numNodes; i++) { - V currentNode = it.next(); - nodes.add(new Node(currentNode)); - indexer.put(currentNode, i); - } - for (int i = 0; i < numNodes; i++) { - V we = nodes.get(i).prototype; - for (E e : network.outgoingEdgesOf(we)) { - V he = network.getEdgeTarget(e); - int j = indexer.get(he); - Arc e1 = new Arc(i, j, network.getEdgeWeight(e), e); - Arc e2 = new Arc(j, i, 0.0, null); - e1.reversed = e2; - e2.reversed = e1; - nodes.get(i).outgoingArcs.add(e1); - nodes.get(j).outgoingArcs.add(e2); - } - } - } - - /** - * Sets current source to source, current sink to sink, - * then calculates maximum flow from source to sink. Note, - * that source and sink must be vertices of the - * network passed to the constructor, and they must be different. - * - * @param source source vertex - * @param sink sink vertex - */ - public void calculateMaximumFlow( - V source, - V sink) - { - if (!network.containsVertex(source)) { - throw new IllegalArgumentException( - "invalid source (null or not from this network)"); - } - if (!network.containsVertex(sink)) { - throw new IllegalArgumentException( - "invalid sink (null or not from this network)"); - } - - if (source.equals(sink)) { - throw new IllegalArgumentException("source is equal to sink"); - } - - currentSource = indexer.get(source); - currentSink = indexer.get(sink); - - for (int i = 0; i < numNodes; i++) { - for (Arc currentArc : nodes.get(i).outgoingArcs) { - currentArc.flow = 0.0; - } - } - maximumFlowValue = 0.0; - for (;;) { - breadthFirstSearch(); - if (!nodes.get(currentSink).visited) { - maximumFlow = new HashMap(); - for (int i = 0; i < numNodes; i++) { - for (Arc currentArc : nodes.get(i).outgoingArcs) { - if (currentArc.prototype != null) { - maximumFlow.put( - currentArc.prototype, - currentArc.flow); - } - } - } - return; - } - augmentFlow(); - } - } - - private void breadthFirstSearch() - { - for (int i = 0; i < numNodes; i++) { - nodes.get(i).visited = false; - } - Queue queue = new LinkedList(); - queue.offer(currentSource); - nodes.get(currentSource).visited = true; - nodes.get(currentSource).flowAmount = Double.POSITIVE_INFINITY; - while (queue.size() != 0) { - int currentNode = queue.poll(); - for (Arc currentArc : nodes.get(currentNode).outgoingArcs) { - if ((currentArc.flow + epsilon) < currentArc.capacity) { - if (!nodes.get(currentArc.head).visited) { - nodes.get(currentArc.head).visited = true; - nodes.get(currentArc.head).flowAmount = - Math.min( - nodes.get(currentNode).flowAmount, - currentArc.capacity - currentArc.flow); - nodes.get(currentArc.head).lastArc = currentArc; - queue.add(currentArc.head); - } - } - } - } - } - - private void augmentFlow() - { - double deltaFlow = nodes.get(currentSink).flowAmount; - maximumFlowValue += deltaFlow; - int currentNode = currentSink; - while (currentNode != currentSource) { - nodes.get(currentNode).lastArc.flow += deltaFlow; - nodes.get(currentNode).lastArc.reversed.flow -= deltaFlow; - currentNode = nodes.get(currentNode).lastArc.tail; - } - } - - /** - * Returns maximum flow value, that was calculated during last - * calculateMaximumFlow call, or null, if there was no - * calculateMaximumFlow calls. - * - * @return maximum flow value - */ - public Double getMaximumFlowValue() - { - return maximumFlowValue; - } - - /** - * Returns maximum flow, that was calculated during last - * calculateMaximumFlow call, or null, if there was no - * calculateMaximumFlow calls. - * - * @return read-only mapping from edges to doubles - flow values - */ - public Map getMaximumFlow() - { - if (maximumFlow == null) { - return null; - } - return Collections.unmodifiableMap(maximumFlow); - } - - /** - * Returns current source vertex, or null if there was no - * calculateMaximumFlow calls. - * - * @return current source - */ - public V getCurrentSource() - { - if (currentSource == -1) { - return null; - } - return nodes.get(currentSource).prototype; - } - - /** - * Returns current sink vertex, or null if there was no - * calculateMaximumFlow calls. - * - * @return current sink - */ - public V getCurrentSink() - { - if (currentSink == -1) { - return null; - } - return nodes.get(currentSink).prototype; - } - - //~ Inner Classes ---------------------------------------------------------- - - // class used for internal representation of network - class Node - { - V prototype; // corresponding node in the original network - List outgoingArcs = new ArrayList(); // list of outgoing arcs - // in the residual - // network - boolean visited; // this mark is used during BFS to mark visited nodes - Arc lastArc; // last arc in the shortest path - double flowAmount; // amount of flow, we are able to push here - - Node( - V prototype) - { - this.prototype = prototype; - } - } - - // class used for internal representation of network - class Arc - { - int tail; // "from" - int head; // "to" - double capacity; // capacity (can be zero) - double flow; // current flow (can be negative) - Arc reversed; // for each arc in the original network we are to create - // reversed arc - E prototype; // corresponding edge in the original network, can be null, - // if it is reversed arc - - Arc( - int tail, - int head, - double capacity, - E prototype) - { - this.tail = tail; - this.head = head; - this.capacity = capacity; - this.prototype = prototype; - } - } -} - -// End EdmondsKarpMaximumFlow.java diff --git a/src/org/jgrapht/alg/EulerianCircuit.java b/src/org/jgrapht/alg/EulerianCircuit.java deleted file mode 100644 index 0ea4e8b..0000000 --- a/src/org/jgrapht/alg/EulerianCircuit.java +++ /dev/null @@ -1,148 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * EulerianCircuit.java - * ------------------- - * (C) Copyright 2008-2008, by Andrew Newell and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 24-Dec-2008 : Initial revision (AN); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - * This algorithm will check whether a graph is Eulerian (hence it contains an - * Eulerian - * circuit). Also, if a graph is Eulerian, the caller can obtain a list of - * vertices making up the Eulerian circuit. An Eulerian circuit is a circuit - * which traverses each edge exactly once. - * - * @author Andrew Newell - * @since Dec 21, 2008 - */ -public abstract class EulerianCircuit -{ - //~ Methods ---------------------------------------------------------------- - - /** - * This method will check whether the graph passed in is Eulerian or not. - * - * @param g The graph to be checked - * - * @return true for Eulerian and false for non-Eulerian - */ - public static boolean isEulerian(UndirectedGraph g) - { - // If the graph is not connected, then no Eulerian circuit exists - if (!(new ConnectivityInspector(g)).isGraphConnected()) { - return false; - } - - // A graph is Eulerian if and only if all vertices have even degree - // So, this code will check for that - Iterator iter = g.vertexSet().iterator(); - while (iter.hasNext()) { - V v = iter.next(); - if ((g.degreeOf(v) % 2) == 1) { - return false; - } - } - return true; - } - - /** - * This method will return a list of vertices which represents the Eulerian - * circuit of the graph. - * - * @param g The graph to find an Eulerian circuit - * - * @return null if no Eulerian circuit exists, or a list of vertices - * representing the Eulerian circuit if one does exist - */ - public static List getEulerianCircuitVertices( - UndirectedGraph g) - { - // If the graph is not Eulerian then just return a null since no - // Eulerian circuit exists - if (!isEulerian(g)) { - return null; - } - - // The circuit will be represented by a linked list - List path = new LinkedList(); - UndirectedGraph sg = new UndirectedSubgraph(g, null, null); - path.add(sg.vertexSet().iterator().next()); - - // Algorithm for finding an Eulerian circuit Basically this will find an - // arbitrary circuit, then it will find another arbitrary circuit until - // every edge has been traversed - while (sg.edgeSet().size() > 0) { - V v = null; - - // Find a vertex which has an edge that hasn't been traversed yet, - // and keep its index position in the circuit list - int index = 0; - for (Iterator iter = path.iterator(); iter.hasNext(); index++) { - v = iter.next(); - if (sg.degreeOf(v) > 0) { - break; - } - } - - // Finds an arbitrary circuit of the current vertex and - // appends this into the circuit list - while (sg.degreeOf(v) > 0) { - for ( - Iterator iter = sg.vertexSet().iterator(); - iter.hasNext();) - { - V temp = iter.next(); - if (sg.containsEdge(v, temp)) { - path.add(index, temp); - sg.removeEdge(v, temp); - v = temp; - break; - } - } - } - } - return path; - } -} - -// End EulerianCircuit.java diff --git a/src/org/jgrapht/alg/FloydWarshallShortestPaths.java b/src/org/jgrapht/alg/FloydWarshallShortestPaths.java deleted file mode 100644 index 6e83410..0000000 --- a/src/org/jgrapht/alg/FloydWarshallShortestPaths.java +++ /dev/null @@ -1,317 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * FloydWarshallShortestPaths.java - * ------------------------- - * (C) Copyright 2009-2009, by Tom Larkworthy and Contributors - * - * Original Author: Tom Larkworthy - * Contributor(s): Soren Davidsen - * - * $Id: FloydWarshallShortestPaths.java 755 2012-01-18 23:50:37Z perfecthash $ - * - * Changes - * ------- - * 29-Jun-2009 : Initial revision (TL); - * 03-Dec-2009 : Optimized and enhanced version (SD); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; -import org.jgrapht.util.*; - - -/** - * The - * Floyd-Warshall algorithm finds all shortest paths (all n^2 of them) in - * O(n^3) time. It can also calculate the graph diameter. - * - * @author Tom Larkworthy - * @author Soren Davidsen - */ -public class FloydWarshallShortestPaths -{ - //~ Instance fields -------------------------------------------------------- - - private Graph graph; - private List vertices; - private int nShortestPaths = 0; - private double diameter = Double.NaN; - private double [][] d = null; - private int [][] backtrace = null; - private Map, GraphPath> paths = null; - - //~ Constructors ----------------------------------------------------------- - - public FloydWarshallShortestPaths(Graph graph) - { - this.graph = graph; - this.vertices = new ArrayList(graph.vertexSet()); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @return the graph on which this algorithm operates - */ - public Graph getGraph() - { - return graph; - } - - /** - * @return total number of shortest paths - */ - public int getShortestPathsCount() - { - lazyCalculatePaths(); - return nShortestPaths; - } - - /** - * Calculates the matrix of all shortest paths, but does not populate the - * paths map. - */ - private void lazyCalculateMatrix() - { - if (d != null) { - // already done - return; - } - - int n = vertices.size(); - - // init the backtrace matrix - backtrace = new int[n][n]; - for (int i = 0; i < n; i++) { - Arrays.fill(backtrace[i], -1); - } - - // initialize matrix, 0 - d = new double[n][n]; - for (int i = 0; i < n; i++) { - Arrays.fill(d[i], Double.POSITIVE_INFINITY); - } - - // initialize matrix, 1 - for (int i = 0; i < n; i++) { - d[i][i] = 0.0; - } - - // initialize matrix, 2 - Set edges = graph.edgeSet(); - for (E edge : edges) { - V v1 = graph.getEdgeSource(edge); - V v2 = graph.getEdgeTarget(edge); - - int v_1 = vertices.indexOf(v1); - int v_2 = vertices.indexOf(v2); - - d[v_1][v_2] = graph.getEdgeWeight(edge); - if (!(graph instanceof DirectedGraph)) { - d[v_2][v_1] = graph.getEdgeWeight(edge); - } - } - - // run fw alg - for (int k = 0; k < n; k++) { - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - double ik_kj = d[i][k] + d[k][j]; - if (ik_kj < d[i][j]) { - d[i][j] = ik_kj; - backtrace[i][j] = k; - } - } - } - } - } - - /** - * Get the length of a shortest path. - * - * @param a first vertex - * @param b second vertex - * - * @return shortest distance between a and b - */ - public double shortestDistance(V a, V b) - { - lazyCalculateMatrix(); - - return d[vertices.indexOf(a)][vertices.indexOf(b)]; - } - - /** - * @return the diameter (longest of all the shortest paths) computed for the - * graph. If the graph is vertexless, return 0.0. - */ - public double getDiameter() - { - lazyCalculateMatrix(); - - if (Double.isNaN(diameter)) { - diameter = 0.0; - int n = vertices.size(); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - if (!Double.isInfinite(d[i][j]) && d[i][j] > diameter) { - diameter = d[i][j]; - } - } - } - } - return diameter; - } - - private void shortestPathRecur(List edges, int v_a, int v_b) - { - int k = backtrace[v_a][v_b]; - if (k == -1) { - E edge = graph.getEdge(vertices.get(v_a), vertices.get(v_b)); - if (edge != null) { - edges.add(edge); - } - } else { - shortestPathRecur(edges, v_a, k); - shortestPathRecur(edges, k, v_b); - } - } - - /** - * Get the shortest path between two vertices. Note: The paths are - * calculated using a recursive algorithm. It *will* give problems on paths - * longer than the stack allows. - * - * @param a From vertice - * @param b To vertice - * - * @return the path, or null if none found - */ - public GraphPath getShortestPath(V a, V b) - { - lazyCalculatePaths(); - return getShortestPathImpl(a, b); - } - - private GraphPath getShortestPathImpl(V a, V b) - { - int v_a = vertices.indexOf(a); - int v_b = vertices.indexOf(b); - - List edges = new ArrayList(); - shortestPathRecur(edges, v_a, v_b); - - // no path, return null - if (edges.size() < 1) { - return null; - } - - GraphPathImpl path = - new GraphPathImpl(graph, a, b, edges, edges.size()); - - return path; - } - - /** - * Calculate the shortest paths (not done per default) - */ - private void lazyCalculatePaths() - { - // already we have calculated it once. - if (paths != null) { - return; - } - - lazyCalculateMatrix(); - - Map, GraphPath> sps = - new HashMap, GraphPath>(); - int n = vertices.size(); - - nShortestPaths = 0; - for (int i = 0; i < n; i++) { - V v_i = vertices.get(i); - for (int j = 0; j < n; j++) { - // don't count this. - if (i == j) { - continue; - } - - V v_j = vertices.get(j); - - GraphPath path = getShortestPathImpl(v_i, v_j); - - // we got a path - if (path != null) { - sps.put(new VertexPair(v_i, v_j), path); - nShortestPaths++; - } - } - } - - this.paths = sps; - } - - /** - * Get shortest paths from a vertex to all other vertices in the graph. - * - * @param v the originating vertex - * - * @return List of paths - */ - public List> getShortestPaths(V v) - { - lazyCalculatePaths(); - List> found = new ArrayList>(); - - // TODO: two-level map for paths so that we don't have to - // iterate over all paths here! - for (VertexPair pair : paths.keySet()) { - if (pair.getFirst().equals(v)) { - found.add(paths.get(pair)); - } - } - - return found; - } - - /** - * Get all shortest paths in the graph. - * - * @return List of paths - */ - public Collection> getShortestPaths() - { - lazyCalculatePaths(); - return paths.values(); - } -} - -// End FloydWarshallShortestPaths.java diff --git a/src/org/jgrapht/alg/HamiltonianCycle.java b/src/org/jgrapht/alg/HamiltonianCycle.java deleted file mode 100644 index 0903f92..0000000 --- a/src/org/jgrapht/alg/HamiltonianCycle.java +++ /dev/null @@ -1,120 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * HamiltonianCycle.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 17-Feb-2008 : Initial revision (AN); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.graph.*; - - -/** - * This class will deal with finding the optimal or approximately optimal - * minimum tour (hamiltonian cycle) or commonly known as the Traveling - * Salesman Problem. - * - * @author Andrew Newell - */ -public class HamiltonianCycle -{ - //~ Methods ---------------------------------------------------------------- - - /** - * This method will return an approximate minimal traveling salesman tour - * (hamiltonian cycle). This algorithm requires that the graph be complete - * and the triangle inequality exists (if x,y,z are vertices then - * d(x,y)+d(y,z) - * @param - * @param g is the graph to find the optimal tour for. - * - * @return The optimal tour as a list of vertices. - */ - public static List getApproximateOptimalForCompleteGraph( - SimpleWeightedGraph g) - { - List vertices = new LinkedList(g.vertexSet()); - - // If the graph is not complete then return null since this algorithm - // requires the graph be complete - if ((vertices.size() * (vertices.size() - 1) / 2) - != g.edgeSet().size()) - { - return null; - } - - List tour = new LinkedList(); - - // Each iteration a new vertex will be added to the tour until all - // vertices have been added - while (tour.size() != g.vertexSet().size()) { - boolean firstEdge = true; - double minEdgeValue = 0; - int minVertexFound = 0; - int vertexConnectedTo = 0; - - // A check will be made for the shortest edge to a vertex not within - // the tour and that new vertex will be added to the vertex - for (int i = 0; i < tour.size(); i++) { - V v = tour.get(i); - for (int j = 0; j < vertices.size(); j++) { - double weight = - g.getEdgeWeight(g.getEdge(v, vertices.get(j))); - if (firstEdge || (weight < minEdgeValue)) { - firstEdge = false; - minEdgeValue = weight; - minVertexFound = j; - vertexConnectedTo = i; - } - } - } - tour.add(vertexConnectedTo, vertices.get(minVertexFound)); - vertices.remove(minVertexFound); - } - return tour; - } -} - -// End HamiltonianCycle.java diff --git a/src/org/jgrapht/alg/KShortestPaths.java b/src/org/jgrapht/alg/KShortestPaths.java deleted file mode 100644 index 4e68251..0000000 --- a/src/org/jgrapht/alg/KShortestPaths.java +++ /dev/null @@ -1,258 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * KShortestPaths.java - * ------------------------- - * (C) Copyright 2007-2010, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * 06-Dec-2010 : Bugfixes (GB); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * The algorithm determines the k shortest simple paths in increasing order of - * weight. Weights can be negative (but no negative cycle is allowed), and paths - * can be constrained by a maximum number of edges. Multigraphs are allowed. - * - *

      The algorithm is a variant of the Bellman-Ford algorithm but instead of - * only storing the best path it stores the "k" best paths at each pass, - * yielding a complexity of O(k*n*(m^2)) where m is the number of edges and n is - * the number of vertices. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class KShortestPaths -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Graph on which shortest paths are searched. - */ - private Graph graph; - - private int nMaxHops; - - private int nPaths; - - private V startVertex; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates an object to compute ranking shortest paths between the start - * vertex and others vertices. - * - * @param graph - * @param startVertex - * @param k number of paths to be computed. - */ - public KShortestPaths(Graph graph, V startVertex, int k) - { - this(graph, startVertex, k, graph.vertexSet().size() - 1); - } - - /** - * Creates an object to calculate ranking shortest paths between the start - * vertex and others vertices. - * - * @param graph graph on which shortest paths are searched. - * @param startVertex start vertex of the calculated paths. - * @param nPaths number of ranking paths between the start vertex and an end - * vertex. - * @param nMaxHops maximum number of edges of the calculated paths. - * - * @throws NullPointerException if the specified graph or startVertex is - * null. - * @throws IllegalArgumentException if nPaths is negative or 0. - * @throws IllegalArgumentException if nMaxHops is negative or 0. - */ - public KShortestPaths( - Graph graph, - V startVertex, - int nPaths, - int nMaxHops) - { - assertKShortestPathsFinder(graph, startVertex, nPaths, nMaxHops); - - this.graph = graph; - this.startVertex = startVertex; - this.nPaths = nPaths; - this.nMaxHops = nMaxHops; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the k shortest simple paths in increasing order of weight. - * - * @param endVertex target vertex of the calculated paths. - * - * @return list of paths, or null if no path exists between the - * start vertex and the end vertex. - */ - public List> getPaths(V endVertex) - { - assertGetPaths(endVertex); - - KShortestPathsIterator iter = - new KShortestPathsIterator( - this.graph, - this.startVertex, - endVertex, - this.nPaths); - - // at the i-th pass the shortest paths with less (or equal) than i edges - // are calculated. - for ( - int passNumber = 1; - (passNumber <= this.nMaxHops) - && iter.hasNext(); - passNumber++) - { - iter.next(); - } - - List> list = iter.getPathElements(endVertex); - - if (list == null) { - return null; - } - - List> pathList = new ArrayList>(); - - for (RankingPathElement element : list) { - pathList.add(new PathWrapper(element)); - } - - return pathList; - } - - private void assertGetPaths(V endVertex) - { - if (endVertex == null) { - throw new NullPointerException("endVertex is null"); - } - if (endVertex.equals(this.startVertex)) { - throw new IllegalArgumentException( - "The end vertex is the same as the start vertex!"); - } - if (!this.graph.vertexSet().contains(endVertex)) { - throw new IllegalArgumentException( - "Graph must contain the end vertex!"); - } - } - - private void assertKShortestPathsFinder( - Graph graph, - V startVertex, - int nPaths, - int nMaxHops) - { - if (graph == null) { - throw new NullPointerException("graph is null"); - } - if (startVertex == null) { - throw new NullPointerException("startVertex is null"); - } - if (nPaths <= 0) { - throw new NullPointerException("nPaths is negative or 0"); - } - if (nMaxHops <= 0) { - throw new NullPointerException("nMaxHops is negative or 0"); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - private class PathWrapper - implements GraphPath - { - private RankingPathElement rankingPathElement; - - private List edgeList; - - PathWrapper(RankingPathElement rankingPathElement) - { - this.rankingPathElement = rankingPathElement; - } - - // implement GraphPath - public Graph getGraph() - { - return graph; - } - - // implement GraphPath - public V getStartVertex() - { - return startVertex; - } - - // implement GraphPath - public V getEndVertex() - { - return rankingPathElement.getVertex(); - } - - // implement GraphPath - public List getEdgeList() - { - if (edgeList == null) { - edgeList = rankingPathElement.createEdgeListPath(); - } - return edgeList; - } - - // implement GraphPath - public double getWeight() - { - return rankingPathElement.getWeight(); - } - - // override Object - public String toString() - { - return getEdgeList().toString(); - } - } -} - -// End KShortestPaths.java diff --git a/src/org/jgrapht/alg/KShortestPathsIterator.java b/src/org/jgrapht/alg/KShortestPathsIterator.java deleted file mode 100644 index 6dca6d1..0000000 --- a/src/org/jgrapht/alg/KShortestPathsIterator.java +++ /dev/null @@ -1,416 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * KShortestPathsIterator.java - * ------------------------- - * (C) Copyright 2007-2010, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * 06-Dec-2010 : Bugfixes (GB); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Helper class for {@link KShortestPaths}. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -class KShortestPathsIterator - implements Iterator> -{ - //~ Instance fields -------------------------------------------------------- - - /** - * End vertex. - */ - private V endVertex; - - /** - * Graph on which shortest paths are searched. - */ - private Graph graph; - - /** - * Number of paths stored at each end vertex. - */ - private int k; - - /** - * Vertices whose ranking shortest paths have been modified during the - * previous pass. - */ - private Set prevImprovedVertices; - - /** - * Stores the paths that improved the vertex in the previous pass. - */ - private Map> prevSeenDataContainer; - - /** - * Stores the vertices that have been seen during iteration and (optionally) - * some additional traversal info regarding each vertex. Key = vertex, value - * = RankingPathElementList list of calculated paths. - */ - private Map> seenDataContainer; - - /** - * Start vertex. - */ - private V startVertex; - - private boolean startVertexEncountered; - - /** - * Stores the number of the path. - */ - private int passNumber = 1; - - //~ Constructors ----------------------------------------------------------- - - /** - * @param graph graph on which shortest paths are searched. - * @param startVertex start vertex of the calculated paths. - * @param endVertex end vertex of the calculated paths. - * @param maxSize number of paths stored at end vertex of the graph. - */ - public KShortestPathsIterator( - Graph graph, - V startVertex, - V endVertex, - int maxSize) - { - assertKShortestPathsIterator(graph, startVertex); - - this.graph = graph; - this.startVertex = startVertex; - this.endVertex = endVertex; - - this.k = maxSize; - - this.seenDataContainer = new HashMap>(); - this.prevSeenDataContainer = - new HashMap>(); - - this.prevImprovedVertices = new HashSet(); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @return true if at least one path has been improved during - * the previous pass, false otherwise. - */ - public boolean hasNext() - { - if (!this.startVertexEncountered) { - encounterStartVertex(); - } - - return !(this.prevImprovedVertices.isEmpty()); - } - - /** - * Returns the list of vertices whose path has been improved during the - * current pass. Complexity = - * - *

        - *
      • O(m*k*(m+n)) where k is the maximum number - * of shortest paths to compute, m is the number of edges of - * the graph and n is the number of vertices of the graph
      • - *
      - * - * @see java.util.Iterator#next() - */ - public Set next() - { - if (!this.startVertexEncountered) { - encounterStartVertex(); - } - - // at the i-th pass the shortest paths with i edges are calculated. - if (hasNext()) { - Set improvedVertices = new HashSet(); - - for ( - Iterator iter = this.prevImprovedVertices.iterator(); - iter.hasNext();) - { - V vertex = iter.next(); - if (!vertex.equals(this.endVertex)) { - updateOutgoingVertices(vertex, improvedVertices); - } - } - - savePassData(improvedVertices); - this.passNumber++; - - return improvedVertices; - } - throw new NoSuchElementException(); - } - - /** - * Unsupported. - * - * @see java.util.Iterator#remove() - */ - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Returns the path elements of the ranking shortest paths with less than - * nMaxHops edges between the start vertex and the end vertex. - * - * @param endVertex end vertex. - * - * @return list of RankingPathElement, or null of - * no path exists between the start vertex and the end vertex. - */ - RankingPathElementList getPathElements(V endVertex) - { - return this.seenDataContainer.get(endVertex); - } - - private void assertKShortestPathsIterator(Graph graph, V startVertex) - { - if (graph == null) { - throw new NullPointerException("graph is null"); - } - if (startVertex == null) { - throw new NullPointerException("startVertex is null"); - } - } - - /** - * The first time we see a vertex, make up a new entry for it. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - * - * @return the new entry. - */ - private RankingPathElementList createSeenData(V vertex, E edge) - { - V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); - - RankingPathElementList oppositeData = - this.prevSeenDataContainer.get(oppositeVertex); - - // endVertex in argument to ensure that stored paths do not disconnect - // the end-vertex - RankingPathElementList data = - new RankingPathElementList( - this.graph, - this.k, - oppositeData, - edge, - this.endVertex); - - return data; - } - - /** - * Returns an iterator to loop over outgoing edges Edge of the - * vertex. - * - * @param vertex - * - * @return . - */ - private Iterator edgesOfIterator(V vertex) - { - if (this.graph instanceof DirectedGraph) { - return ((DirectedGraph) this.graph).outgoingEdgesOf(vertex) - .iterator(); - } else { - return this.graph.edgesOf(vertex).iterator(); - } - } - - /** - * Initializes the list of paths at the start vertex and adds an empty path. - */ - private void encounterStartVertex() - { - RankingPathElementList data = - new RankingPathElementList( - this.graph, - this.k, - new RankingPathElement( - this.startVertex)); - - this.seenDataContainer.put(this.startVertex, data); - this.prevSeenDataContainer.put(this.startVertex, data); - - // initially the only vertex whose value is considered to have changed - // is the start vertex - this.prevImprovedVertices.add(this.startVertex); - - this.startVertexEncountered = true; - } - - private void savePassData(Set improvedVertices) - { - for (Iterator iter = improvedVertices.iterator(); iter.hasNext();) { - V vertex = iter.next(); - - RankingPathElementList pathElementList = - this.seenDataContainer.get(vertex); - - RankingPathElementList improvedPaths = - new RankingPathElementList( - this.graph, - pathElementList.maxSize, - vertex); - - for ( - Iterator> pathIter = - pathElementList.iterator(); - pathIter.hasNext();) - { - RankingPathElement path = pathIter.next(); - if (path.getHopCount() == this.passNumber) { - // the path has just been computed. - improvedPaths.pathElements.add(path); - } - } - - this.prevSeenDataContainer.put(vertex, improvedPaths); - } - - this.prevImprovedVertices = improvedVertices; - } - - /** - * Try to add the first paths to the specified vertex. These paths reached - * the specified vertex and ended with the specified edge. A new - * intermediary path is stored in the paths list of the specified vertex - * provided that the path can be extended to the end-vertex. - * - * @param vertex vertex reached by a path. - * @param edge edge reaching the vertex. - */ - private boolean tryToAddFirstPaths(V vertex, E edge) - { - // the vertex has not been reached yet - RankingPathElementList data = createSeenData(vertex, edge); - - if (!data.isEmpty()) { - this.seenDataContainer.put(vertex, data); - return true; - } - return false; - } - - /** - * Try to add new paths for the vertex. These new paths reached the - * specified vertex and ended with the specified edge. A new intermediary - * path is stored in the paths list of the specified vertex provided that - * the path can be extended to the end-vertex. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - */ - private boolean tryToAddNewPaths(V vertex, E edge) - { - RankingPathElementList data = this.seenDataContainer.get(vertex); - - V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); - RankingPathElementList oppositeData = - this.prevSeenDataContainer.get(oppositeVertex); - - return data.addPathElements(oppositeData, edge); - } - - /** - *

      Updates outgoing vertices of the vertex. For each outgoing vertex, the - * new paths are obtained by concatenating the specified edge to the - * calculated paths of the specified vertex. If the weight of a new path is - * greater than the weight of any path stored so far at the outgoing vertex - * then the path is not added, otherwise it is added to the list of paths in - * increasing order of weight.

      - * - * Complexity = - * - *
        - *
      • O(d(v)*k*(m+n)) where d(v) is the outgoing - * degree of the specified vertex, k is the maximum number of - * shortest paths to compute, m is the number of edges of the - * graph and n is the number of vertices of the graph
      • - *
      - * - * @param vertex - * @param improvedVertices - */ - private void updateOutgoingVertices(V vertex, Set improvedVertices) - { - // try to add new paths for the target vertices of the outgoing edges - // of the vertex in argument. - for (Iterator iter = edgesOfIterator(vertex); iter.hasNext();) { - E edge = iter.next(); - V vertexReachedByEdge = - Graphs.getOppositeVertex(this.graph, edge, - vertex); - - // check if the path does not loop over the start vertex. - if (vertexReachedByEdge != this.startVertex) { - if (this.seenDataContainer.containsKey(vertexReachedByEdge)) { - boolean relaxed = - tryToAddNewPaths(vertexReachedByEdge, - edge); - if (relaxed) { - improvedVertices.add(vertexReachedByEdge); - } - } else { - boolean relaxed = - tryToAddFirstPaths(vertexReachedByEdge, - edge); - if (relaxed) { - improvedVertices.add(vertexReachedByEdge); - } - } - } - } - } -} - -// End KShortestPathsIterator.java diff --git a/src/org/jgrapht/alg/KruskalMinimumSpanningTree.java b/src/org/jgrapht/alg/KruskalMinimumSpanningTree.java deleted file mode 100644 index 574bb15..0000000 --- a/src/org/jgrapht/alg/KruskalMinimumSpanningTree.java +++ /dev/null @@ -1,126 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * KruskalMinimumSpanningTree.java - * ------------------------- - * (C) Copyright 2010-2010, by Tom Conerly and Contributors. - * - * Original Author: Tom Conerly - * Contributor(s): - * - * Changes - * ------- - * 02-Feb-2010 : Initial revision (TC); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.alg.util.*; - - -/** - * An implementation of Kruskal's minimum - * spanning tree algorithm. If the given graph is connected it computes the - * minimum spanning tree, otherwise it computes the minimum spanning forest. The - * algorithm runs in time O(E log E). This implementation uses the hashCode and - * equals method of the vertices. - * - * @author Tom Conerly - * @since Feb 10, 2010 - */ -public class KruskalMinimumSpanningTree -{ - //~ Instance fields -------------------------------------------------------- - - private double spanningTreeCost; - private Set edgeList; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates and executes a new KruskalMinimumSpanningTree algorithm instance. - * An instance is only good for a single spanning tree; after construction, - * it can be accessed to retrieve information about the spanning tree found. - * - * @param graph the graph to be searched - */ - public KruskalMinimumSpanningTree(final Graph graph) - { - UnionFind forest = new UnionFind(graph.vertexSet()); - ArrayList allEdges = new ArrayList(graph.edgeSet()); - Collections.sort( - allEdges, - new Comparator() { - public int compare(E edge1, E edge2) - { - return Double.valueOf(graph.getEdgeWeight(edge1)).compareTo( - graph.getEdgeWeight(edge2)); - } - }); - - spanningTreeCost = 0; - edgeList = new HashSet(); - - for (E edge : allEdges) { - V source = graph.getEdgeSource(edge); - V target = graph.getEdgeTarget(edge); - if (forest.find(source).equals(forest.find(target))) { - continue; - } - - forest.union(source, target); - edgeList.add(edge); - spanningTreeCost += graph.getEdgeWeight(edge); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the edges making up the tree found. - * - * @return Set of Edges - */ - public Set getEdgeSet() - { - return edgeList; - } - - /** - * Returns the cost of the minimum spanning tree or forest. - * - * @return Cost of the spanning tree - */ - public double getSpanningTreeCost() - { - return spanningTreeCost; - } -} - -// End KruskalMinimumSpanningTree.java diff --git a/src/org/jgrapht/alg/NeighborIndex.java b/src/org/jgrapht/alg/NeighborIndex.java deleted file mode 100644 index 36bfa82..0000000 --- a/src/org/jgrapht/alg/NeighborIndex.java +++ /dev/null @@ -1,262 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * NeighborIndex.java - * -------------------------- - * (C) Copyright 2005-2008, by Charles Fry and Contributors. - * - * Original Author: Charles Fry - * - * $Id$ - * - * Changes - * ------- - * 13-Dec-2005 : Initial revision (CF); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; -import org.jgrapht.util.*; - - -/** - * Maintains a cache of each vertex's neighbors. While lists of neighbors can be - * obtained from {@link Graphs}, they are re-calculated at each invocation by - * walking a vertex's incident edges, which becomes inordinately expensive when - * performed often. - * - *

      Edge direction is ignored when evaluating neighbors; to take edge - * direction into account when indexing neighbors, use {@link - * DirectedNeighborIndex}. - * - *

      A vertex's neighbors are cached the first time they are asked for (i.e. - * the index is built on demand). The index will only be updated automatically - * if it is added to the associated graph as a listener. If it is added as a - * listener to a graph other than the one it indexes, results are undefined.

      - * - * @author Charles Fry - * @since Dec 13, 2005 - */ -public class NeighborIndex - implements GraphListener -{ - //~ Instance fields -------------------------------------------------------- - - Map> neighborMap = new HashMap>(); - private Graph graph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a neighbor index for the specified undirected graph. - * - * @param g the graph for which a neighbor index is to be created. - */ - public NeighborIndex(Graph g) - { - // no need to distinguish directedgraphs as we don't do traversals - graph = g; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the set of vertices which are adjacent to a specified vertex. The - * returned set is backed by the index, and will be updated when the graph - * changes as long as the index has been added as a listener to the graph. - * - * @param v the vertex whose neighbors are desired - * - * @return all unique neighbors of the specified vertex - */ - public Set neighborsOf(V v) - { - return getNeighbors(v).getNeighbors(); - } - - /** - * Returns a list of vertices which are adjacent to a specified vertex. If - * the graph is a multigraph, vertices may appear more than once in the - * returned list. Because a list of neighbors can not be efficiently - * maintained, it is reconstructed on every invocation, by duplicating - * entries in the neighbor set. It is thus more efficient to use {@link - * #neighborsOf(Object)} unless duplicate neighbors are important. - * - * @param v the vertex whose neighbors are desired - * - * @return all neighbors of the specified vertex - */ - public List neighborListOf(V v) - { - return getNeighbors(v).getNeighborList(); - } - - /** - * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) - */ - public void edgeAdded(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - V source = graph.getEdgeSource(edge); - V target = graph.getEdgeTarget(edge); - - // if a map does not already contain an entry, - // then skip addNeighbor, since instantiating the map - // will take care of processing the edge (which has already - // been added) - - if (neighborMap.containsKey(source)) { - getNeighbors(source).addNeighbor(target); - } else { - getNeighbors(source); - } - if (neighborMap.containsKey(target)) { - getNeighbors(target).addNeighbor(source); - } else { - getNeighbors(target); - } - } - - /** - * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) - */ - public void edgeRemoved(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - V source = e.getEdgeSource(); - V target = e.getEdgeTarget(); - if (neighborMap.containsKey(source)) { - neighborMap.get(source).removeNeighbor(target); - } - if (neighborMap.containsKey(target)) { - neighborMap.get(target).removeNeighbor(source); - } - } - - /** - * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) - */ - public void vertexAdded(GraphVertexChangeEvent e) - { - // nothing to cache until there are edges - } - - /** - * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) - */ - public void vertexRemoved(GraphVertexChangeEvent e) - { - neighborMap.remove(e.getVertex()); - } - - private Neighbors getNeighbors(V v) - { - Neighbors neighbors = neighborMap.get(v); - if (neighbors == null) { - neighbors = new Neighbors(v, - Graphs.neighborListOf(graph, v)); - neighborMap.put(v, neighbors); - } - return neighbors; - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Stores cached neighbors for a single vertex. Includes support for live - * neighbor sets and duplicate neighbors. - */ - static class Neighbors - { - private Map neighborCounts = - new LinkedHashMap(); - - // TODO could eventually make neighborSet modifiable, resulting - // in edge removals from the graph - private Set neighborSet = - Collections.unmodifiableSet( - neighborCounts.keySet()); - - public Neighbors(V v, Collection neighbors) - { - // add all current neighbors - for (V neighbor : neighbors) { - addNeighbor(neighbor); - } - } - - public void addNeighbor(V v) - { - ModifiableInteger count = neighborCounts.get(v); - if (count == null) { - count = new ModifiableInteger(1); - neighborCounts.put(v, count); - } else { - count.increment(); - } - } - - public void removeNeighbor(V v) - { - ModifiableInteger count = neighborCounts.get(v); - if (count == null) { - throw new IllegalArgumentException( - "Attempting to remove a neighbor that wasn't present"); - } - - count.decrement(); - if (count.getValue() == 0) { - neighborCounts.remove(v); - } - } - - public Set getNeighbors() - { - return neighborSet; - } - - public List getNeighborList() - { - List neighbors = new ArrayList(); - for ( - Map.Entry entry - : neighborCounts.entrySet()) - { - V v = entry.getKey(); - int count = entry.getValue().intValue(); - for (int i = 0; i < count; i++) { - neighbors.add(v); - } - } - return neighbors; - } - } -} - -// End NeighborIndex.java diff --git a/src/org/jgrapht/alg/RankingPathElement.java b/src/org/jgrapht/alg/RankingPathElement.java deleted file mode 100644 index 0ee3047..0000000 --- a/src/org/jgrapht/alg/RankingPathElement.java +++ /dev/null @@ -1,115 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * RankingPathElement.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import org.jgrapht.*; - - -/** - * Helper class for {@link KShortestPaths}. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -final class RankingPathElement - extends AbstractPathElement -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Weight of the path. - */ - private double weight; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a path element by concatenation of an edge to a path element. - * - * @param pathElement - * @param edge edge reaching the end vertex of the path element created. - * @param weight total cost of the created path element. - */ - RankingPathElement( - Graph graph, - RankingPathElement pathElement, - E edge, - double weight) - { - super(graph, pathElement, edge); - this.weight = weight; - } - - /** - * Creates an empty path element. - * - * @param vertex end vertex of the path element. - */ - RankingPathElement(V vertex) - { - super(vertex); - this.weight = 0; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the weight of the path. - * - * @return . - */ - public double getWeight() - { - return this.weight; - } - - /** - * Returns the previous path element. - * - * @return null is the path is empty. - */ - public RankingPathElement getPrevPathElement() - { - return (RankingPathElement) super.getPrevPathElement(); - } -} - -// End RankingPathElement.java diff --git a/src/org/jgrapht/alg/RankingPathElementList.java b/src/org/jgrapht/alg/RankingPathElementList.java deleted file mode 100644 index 532fcc7..0000000 --- a/src/org/jgrapht/alg/RankingPathElementList.java +++ /dev/null @@ -1,436 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * RankingPathElementList.java - * ------------------------- - * (C) Copyright 2007-2010, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * 06-Dec-2010 : Bugfixes (GB); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - * List of simple paths in increasing order of weight. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -final class RankingPathElementList - extends AbstractPathElementList> -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Vertex that paths of the list must not disconnect. - */ - private V guardVertexToNotDisconnect = null; - - private Map, Boolean> path2disconnect = - new HashMap, Boolean>(); - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a list with an empty path. The list size is 1. - * - * @param maxSize max number of paths the list is able to store. - */ - RankingPathElementList( - Graph graph, - int maxSize, - RankingPathElement pathElement) - { - super(graph, maxSize, pathElement); - } - - /** - * Creates paths obtained by concatenating the specified edge to the - * specified paths. - * - * @param prevPathElementList paths, list of - * RankingPathElement. - * @param edge edge reaching the end vertex of the created paths. - * @param maxSize maximum number of paths the list is able to store. - */ - RankingPathElementList( - Graph graph, - int maxSize, - RankingPathElementList elementList, - E edge) - { - this(graph, maxSize, elementList, edge, null); - - assert (!this.pathElements.isEmpty()); - } - - /** - * Creates paths obtained by concatenating the specified edge to the - * specified paths. - * - * @param prevPathElementList paths, list of - * RankingPathElement. - * @param edge edge reaching the end vertex of the created paths. - * @param maxSize maximum number of paths the list is able to store. - */ - RankingPathElementList( - Graph graph, - int maxSize, - RankingPathElementList elementList, - E edge, - V guardVertexToNotDisconnect) - { - super(graph, maxSize, elementList, edge); - this.guardVertexToNotDisconnect = guardVertexToNotDisconnect; - - // loop over the path elements in increasing order of weight. - for (int i = 0; i < elementList.size(); i++) { - RankingPathElement prevPathElement = elementList.get(i); - - if (isNotValidPath(prevPathElement, edge)) { - continue; - } - - if (size() < this.maxSize) { - double weight = calculatePathWeight(prevPathElement, edge); - RankingPathElement newPathElement = - new RankingPathElement( - this.graph, - prevPathElement, - edge, - weight); - - // the new path is inserted at the end of the list. - this.pathElements.add(newPathElement); - } - } - } - - /** - * Creates an empty list. The list size is 0. - * - * @param maxSize max number of paths the list is able to store. - */ - RankingPathElementList(Graph graph, int maxSize, V vertex) - { - super(graph, maxSize, vertex); - } - - //~ Methods ---------------------------------------------------------------- - - /** - *

      Adds paths in the list at vertex y. Candidate paths are obtained by - * concatenating the specified edge (v->y) to the paths - * elementList at vertex v.

      - * - * Complexity = - * - *
        - *
      • w/o guard-vertex: O(k*np) where k is the - * max size limit of the list and np is the maximum number of - * vertices in the paths stored in the list
      • - *
      • with guard-vertex: O(k*(m+n)) where k is - * the max size limit of the list, m is the number of edges of - * the graph and n is the number of vertices of the graph, - * O(m+n) being the complexity of the - * ConnectivityInspector to check whether a path exists towards the - * guard-vertex
      • - *
      - * - * @param elementList list of paths at vertex v. - * @param edge edge (v->y). - * - * @return true if at least one path has been added in the - * list, false otherwise. - */ - public boolean addPathElements( - RankingPathElementList elementList, - E edge) - { - assert (this.vertex.equals( - Graphs.getOppositeVertex( - this.graph, - edge, - elementList.getVertex()))); - - boolean pathAdded = false; - - // loop over the paths elements of the list at vertex v. - for ( - int vIndex = 0, yIndex = 0; - vIndex < elementList.size(); - vIndex++) - { - RankingPathElement prevPathElement = elementList.get(vIndex); - - if (isNotValidPath(prevPathElement, edge)) { - // checks if path is simple and if guard-vertex is not - // disconnected. - continue; - } - double newPathWeight = calculatePathWeight(prevPathElement, edge); - RankingPathElement newPathElement = - new RankingPathElement( - this.graph, - prevPathElement, - edge, - newPathWeight); - - // loop over the paths of the list at vertex y from yIndex to the - // end. - RankingPathElement yPathElement = null; - for (; yIndex < size(); yIndex++) { - yPathElement = get(yIndex); - - // case when the new path is shorter than the path Py stored at - // index y - if (newPathWeight < yPathElement.getWeight()) { - this.pathElements.add(yIndex, newPathElement); - pathAdded = true; - - // ensures max size limit is not exceeded. - if (size() > this.maxSize) { - this.pathElements.remove(this.maxSize); - } - break; - } - - // case when the new path is of the same length as the path Py - // stored at index y - if (newPathWeight == yPathElement.getWeight()) { - this.pathElements.add(yIndex + 1, newPathElement); - pathAdded = true; - - // ensures max size limit is not exceeded. - if (size() > this.maxSize) { - this.pathElements.remove(this.maxSize); - } - break; - } - } - - // case when the new path is longer than the longest path in the - // list (Py stored at the last index y) - if (newPathWeight > yPathElement.getWeight()) { - // ensures max size limit is not exceeded. - if (size() < this.maxSize) { - // the new path is inserted at the end of the list. - this.pathElements.add(newPathElement); - pathAdded = true; - } else { - // max size limit is reached -> end of the loop over the - // paths elements of the list at vertex v. - break; - } - } - } - - return pathAdded; - } - - /** - * @return list of RankingPathElement. - */ - List> getPathElements() - { - return this.pathElements; - } - - /** - * Costs taken into account are the weights stored in Edge - * objects. - * - * @param pathElement - * @param edge the edge via which the vertex was encountered. - * - * @return the cost obtained by concatenation. - * - * @see Graph#getEdgeWeight(E) - */ - private double calculatePathWeight( - RankingPathElement pathElement, - E edge) - { - double pathWeight = this.graph.getEdgeWeight(edge); - - // otherwise it's the start vertex. - if ((pathElement.getPrevEdge() != null)) { - pathWeight += pathElement.getWeight(); - } - - return pathWeight; - } - - /** - * Ensures that paths of the list do not disconnect the guard-vertex. - * - * @return true if the specified path element disconnects the - * guard-vertex, false otherwise. - */ - private boolean isGuardVertexDisconnected( - RankingPathElement prevPathElement) - { - if (this.guardVertexToNotDisconnect == null) { - return false; - } - - if (this.path2disconnect.containsKey(prevPathElement)) { - return this.path2disconnect.get(prevPathElement); - } - - ConnectivityInspector connectivityInspector; - MaskFunctor connectivityMask; - - if (this.graph instanceof DirectedGraph) { - connectivityMask = new PathMask(prevPathElement); - DirectedMaskSubgraph connectivityGraph = - new DirectedMaskSubgraph( - (DirectedGraph) this.graph, - connectivityMask); - connectivityInspector = - new ConnectivityInspector( - connectivityGraph); - } else { - connectivityMask = new PathMask(prevPathElement); - UndirectedMaskSubgraph connectivityGraph = - new UndirectedMaskSubgraph( - (UndirectedGraph) this.graph, - connectivityMask); - connectivityInspector = - new ConnectivityInspector( - connectivityGraph); - } - - if (connectivityMask.isVertexMasked(this.guardVertexToNotDisconnect)) { - // the guard-vertex was already in the path element -> invalid path - this.path2disconnect.put(prevPathElement, true); - return true; - } - - if (!connectivityInspector.pathExists( - this.vertex, - this.guardVertexToNotDisconnect)) - { - this.path2disconnect.put(prevPathElement, true); - return true; - } - - this.path2disconnect.put(prevPathElement, false); - return false; - } - - private boolean isNotValidPath( - RankingPathElement prevPathElement, - E edge) - { - return !isSimplePath(prevPathElement, edge) - || isGuardVertexDisconnected(prevPathElement); - } - - /** - * Ensures that paths of the list are simple (check that the vertex was not - * already in the path element). - * - * @param prevPathElement - * @param edge - * - * @return true if the resulting path (obtained by - * concatenating the specified edge to the specified path) is simple, - * false otherwise. - */ - private boolean isSimplePath( - RankingPathElement prevPathElement, - E edge) - { - RankingPathElement pathElementToTest = prevPathElement; - while (pathElementToTest.getPrevEdge() != null) { - if (pathElementToTest.getVertex() == this.vertex) { - return false; - } else { - pathElementToTest = pathElementToTest.getPrevPathElement(); - } - } - - return true; - } - - //~ Inner Classes ---------------------------------------------------------- - - private static class PathMask - implements MaskFunctor - { - private Set maskedEdges; - - private Set maskedVertices; - - /** - * Creates a mask for all the edges and the vertices of the path - * (including the 2 extremity vertices). - * - * @param pathElement - */ - PathMask(RankingPathElement pathElement) - { - this.maskedEdges = new HashSet(); - this.maskedVertices = new HashSet(); - - while (pathElement.getPrevEdge() != null) { - this.maskedEdges.add(pathElement.getPrevEdge()); - this.maskedVertices.add(pathElement.getVertex()); - pathElement = pathElement.getPrevPathElement(); - } - this.maskedVertices.add(pathElement.getVertex()); - } - - // implement MaskFunctor - public boolean isEdgeMasked(E edge) - { - return this.maskedEdges.contains(edge); - } - - // implement MaskFunctor - public boolean isVertexMasked(V vertex) - { - return this.maskedVertices.contains(vertex); - } - } -} - -// End RankingPathElementList.java diff --git a/src/org/jgrapht/alg/StoerWagnerMinimumCut.java b/src/org/jgrapht/alg/StoerWagnerMinimumCut.java deleted file mode 100644 index 3fecb74..0000000 --- a/src/org/jgrapht/alg/StoerWagnerMinimumCut.java +++ /dev/null @@ -1,283 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2011, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * StoerWagnerMinimumCut.java - * ---------------- - * (C) Copyright 2011-2011, by Robby McKilliam and Contributors. - * - * Original Author: Robby McKilliam - * Contributor(s): - - * - * $Id: StoerWagnerMinimumCut.java $ - * - * Changes - * ------- - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; -import org.jgrapht.util.*; - - -/** - * Implements the Stoer and - * Wagner minimum cut algorithm. Deterministically computes the minimum cut - * in O(|V||E| + |V|log|V|) time. This implementation uses Java's PriorityQueue - * and requires O(|V||E|log|E|) time. M. Stoer and F. Wagner, "A Simple Min-Cut - * Algorithm", Journal of the ACM, volume 44, number 4. pp 585-591, 1997. - * - * @author Robby McKilliam - */ -public class StoerWagnerMinimumCut -{ - //~ Instance fields -------------------------------------------------------- - - final WeightedGraph, DefaultWeightedEdge> workingGraph; - - double bestcutweight = Double.POSITIVE_INFINITY; - Set bestCut; - - boolean firstRun = true; - - //~ Constructors ----------------------------------------------------------- - - /** - * Will compute the minimum cut in graph. - * - * @param graph graph over which to run algorithm - */ - public StoerWagnerMinimumCut(WeightedGraph graph) - { - //get a version of this graph where each vertex is wrapped with a list - workingGraph = - new SimpleWeightedGraph, DefaultWeightedEdge>( - DefaultWeightedEdge.class); - Map> vertexMap = new HashMap>(); - for (V v : graph.vertexSet()) { - Set list = new HashSet(); - list.add(v); - vertexMap.put(v, list); - workingGraph.addVertex(list); - } - for (E e : graph.edgeSet()) { - V s = graph.getEdgeSource(e); - Set sNew = vertexMap.get(s); - V t = graph.getEdgeTarget(e); - Set tNew = vertexMap.get(t); - DefaultWeightedEdge eNew = workingGraph.addEdge(sNew, tNew); - workingGraph.setEdgeWeight(eNew, graph.getEdgeWeight(e)); - } - - //arbitrary vertex used to seed the algorithm. - Set a = workingGraph.vertexSet().iterator().next(); - while (workingGraph.vertexSet().size() > 2) { - minimumCutPhase(a); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Implements the MinimumCutPhase function of Stoer and Wagner - */ - protected void minimumCutPhase(Set a) - { - //construct sorted queue with vertices connected to vertex a - PriorityQueue queue = - new PriorityQueue(); - Map, VertexAndWeight> dmap = - new HashMap, VertexAndWeight>(); - for (Set v : workingGraph.vertexSet()) { - if (v != a) { - Double w = - -workingGraph.getEdgeWeight(workingGraph.getEdge(v, a)); - VertexAndWeight vandw = new VertexAndWeight(v, w); - queue.add(vandw); - dmap.put(v, vandw); - } - } - - //now iteratatively update the queue to get the required vertex ordering - List> list = - new ArrayList>(workingGraph.vertexSet().size()); - list.add(a); - while (!queue.isEmpty()) { - Set v = queue.poll().vertex; - dmap.remove(v); - list.add(v); - for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) { - Set vc; - if (v != workingGraph.getEdgeSource(e)) { - vc = workingGraph.getEdgeSource(e); - } else { - vc = workingGraph.getEdgeTarget(e); - } - if (dmap.get(vc) != null) { - Double neww = - -workingGraph.getEdgeWeight(workingGraph.getEdge(v, vc)) - + dmap.get(vc).weight; - queue.remove(dmap.get(vc)); //this is O(logn) but could be - //O(1)? - dmap.get(vc).weight = neww; - queue.add(dmap.get(vc)); //this is O(logn) but could be - //O(1)? - } - } - } - - //if this is the first run we compute the weight of last vertex in the - //list - if (firstRun) { - Set v = list.get(list.size() - 1); - double w = vertexWeight(v); - if (w < bestcutweight) { - bestcutweight = w; - bestCut = v; - } - firstRun = false; - } - - //the last two elements in list are the vertices we want to merge. - Set s = list.get(list.size() - 2); - Set t = list.get(list.size() - 1); - - //merge these vertices and get the weight. - VertexAndWeight vw = mergeVertices(s, t); - - //If this is the best cut so far store it. - if (vw.weight < bestcutweight) { - bestcutweight = vw.weight; - bestCut = vw.vertex; - } - } - - /** - * Return the weight of the minimum cut - */ - public double minCutWeight() - { - return bestcutweight; - } - - /** - * Return a set of vertices on one side of the cut - */ - public Set minCut() - { - return bestCut; - } - - /** - * Merges vertex t into vertex s, summing the weights as required. Returns - * the merged vertex and the sum of its weights - */ - protected VertexAndWeight mergeVertices(Set s, Set t) - { - //construct the new combinedvertex - Set set = new HashSet(); - for (V v : s) { - set.add(v); - } - for (V v : t) { - set.add(v); - } - workingGraph.addVertex(set); - - //add edges and weights to the combined vertex - double wsum = 0.0; - for (Set v : workingGraph.vertexSet()) { - if ((s != v) && (t != v)) { - DefaultWeightedEdge etv = workingGraph.getEdge(t, v); - DefaultWeightedEdge esv = workingGraph.getEdge(s, v); - double wtv = 0.0, wsv = 0.0; - if (etv != null) { - wtv = workingGraph.getEdgeWeight(etv); - } - if (esv != null) { - wsv = workingGraph.getEdgeWeight(esv); - } - double neww = wtv + wsv; - wsum += neww; - if (neww != 0.0) { - workingGraph.setEdgeWeight( - workingGraph.addEdge(set, v), - neww); - } - } - } - - //remove original vertices - workingGraph.removeVertex(t); - workingGraph.removeVertex(s); - - return new VertexAndWeight(set, wsum); - } - - /** - * Compute the sum of the weights entering a vertex - */ - public double vertexWeight(Set v) - { - double wsum = 0.0; - for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) { - wsum += workingGraph.getEdgeWeight(e); - } - return wsum; - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Class for weighted vertices - */ - protected class VertexAndWeight - implements Comparable - { - public Set vertex; - public Double weight; - - public VertexAndWeight(Set v, double w) - { - this.vertex = v; - this.weight = w; - } - - @Override public int compareTo(VertexAndWeight that) - { - return Double.compare(weight, that.weight); - } - - @Override public String toString() - { - return "(" + vertex + ", " + weight + ")"; - } - } -} - -// End StoerWagnerMinimumCut.java diff --git a/src/org/jgrapht/alg/StrongConnectivityInspector.java b/src/org/jgrapht/alg/StrongConnectivityInspector.java deleted file mode 100644 index 2dd92ed..0000000 --- a/src/org/jgrapht/alg/StrongConnectivityInspector.java +++ /dev/null @@ -1,393 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * StrongConnectivityInspector.java - * -------------------------- - * (C) Copyright 2005-2008, by Christian Soltenborn and Contributors. - * - * Original Author: Christian Soltenborn - * - * $Id$ - * - * Changes - * ------- - * 2-Feb-2005 : Initial revision (CS); - * 5-Feb-2007 : fixed NullPointerException (CS); - * 1-Apr-2008 : Reduced memory consumption (CS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - *

      Complements the {@link org.jgrapht.alg.ConnectivityInspector} class with - * the capability to compute the strongly connected components of a directed - * graph. The algorithm is implemented after "Cormen et al: Introduction to - * agorithms", Chapter 22.5. It has a running time of O(V + E).

      - * - *

      Unlike {@link org.jgrapht.alg.ConnectivityInspector}, this class does not - * implement incremental inspection. The full algorithm is executed at the first - * call of {@link StrongConnectivityInspector#stronglyConnectedSets()} or {@link - * StrongConnectivityInspector#isStronglyConnected()}.

      - * - * @author Christian Soltenborn - * @author Christian Hammer - * @since Feb 2, 2005 - */ -public class StrongConnectivityInspector -{ - //~ Instance fields -------------------------------------------------------- - - // the graph to compute the strongly connected sets for - private final DirectedGraph graph; - - // stores the vertices, ordered by their finishing time in first dfs - private LinkedList> orderedVertices; - - // the result of the computation, cached for future calls - private List> stronglyConnectedSets; - - // the result of the computation, cached for future calls - private List> stronglyConnectedSubgraphs; - - // maps vertices to their VertexData object - private Map> vertexToVertexData; - - //~ Constructors ----------------------------------------------------------- - - /** - * The constructor of the StrongConnectivityInspector class. - * - * @param directedGraph the graph to inspect - * - * @throws IllegalArgumentException - */ - public StrongConnectivityInspector(DirectedGraph directedGraph) - { - if (directedGraph == null) { - throw new IllegalArgumentException("null not allowed for graph!"); - } - - graph = directedGraph; - vertexToVertexData = null; - orderedVertices = null; - stronglyConnectedSets = null; - stronglyConnectedSubgraphs = null; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the graph inspected by the StrongConnectivityInspector. - * - * @return the graph inspected by this StrongConnectivityInspector - */ - public DirectedGraph getGraph() - { - return graph; - } - - /** - * Returns true if the graph of this - * StronglyConnectivityInspector instance is strongly connected. - * - * @return true if the graph is strongly connected, false otherwise - */ - public boolean isStronglyConnected() - { - return stronglyConnectedSets().size() == 1; - } - - /** - * Computes a {@link List} of {@link Set}s, where each set contains vertices - * which together form a strongly connected component within the given - * graph. - * - * @return List of Set s containing the strongly - * connected components - */ - public List> stronglyConnectedSets() - { - if (stronglyConnectedSets == null) { - orderedVertices = new LinkedList>(); - stronglyConnectedSets = new Vector>(); - - // create VertexData objects for all vertices, store them - createVertexData(); - - // perform the first round of DFS, result is an ordering - // of the vertices by decreasing finishing time - for (VertexData data : vertexToVertexData.values()) { - if (!data.isDiscovered()) { - dfsVisit(graph, data, null); - } - } - - // 'create' inverse graph (i.e. every edge is reversed) - DirectedGraph inverseGraph = - new EdgeReversedGraph(graph); - - // get ready for next dfs round - resetVertexData(); - - // second dfs round: vertices are considered in decreasing - // finishing time order; every tree found is a strongly - // connected set - for (VertexData data : orderedVertices) { - if (!data.isDiscovered()) { - // new strongly connected set - Set set = new HashSet(); - stronglyConnectedSets.add(set); - dfsVisit(inverseGraph, data, set); - } - } - - // clean up for garbage collection - orderedVertices = null; - vertexToVertexData = null; - } - - return stronglyConnectedSets; - } - - /** - *

      Computes a list of {@link DirectedSubgraph}s of the given graph. Each - * subgraph will represent a strongly connected component and will contain - * all vertices of that component. The subgraph will have an edge (u,v) iff - * u and v are contained in the strongly connected component.

      - * - *

      NOTE: Calling this method will first execute {@link - * StrongConnectivityInspector#stronglyConnectedSets()}. If you don't need - * subgraphs, use that method.

      - * - * @return a list of subgraphs representing the strongly connected - * components - */ - public List> stronglyConnectedSubgraphs() - { - if (stronglyConnectedSubgraphs == null) { - List> sets = stronglyConnectedSets(); - stronglyConnectedSubgraphs = - new Vector>(sets.size()); - - for (Set set : sets) { - stronglyConnectedSubgraphs.add( - new DirectedSubgraph( - graph, - set, - null)); - } - } - - return stronglyConnectedSubgraphs; - } - - /* - * Creates a VertexData object for every vertex in the graph and stores - * them - * in a HashMap. - */ - private void createVertexData() - { - vertexToVertexData = - new HashMap>(graph.vertexSet().size()); - - for (V vertex : graph.vertexSet()) { - vertexToVertexData.put( - vertex, - new VertexData2(vertex, false, false)); - } - } - - /* - * The subroutine of DFS. NOTE: the set is used to distinguish between 1st - * and 2nd round of DFS. set == null: finished vertices are stored (1st - * round). set != null: all vertices found will be saved in the set (2nd - * round) - */ - private void dfsVisit( - DirectedGraph visitedGraph, - VertexData vertexData, - Set vertices) - { - Deque> stack = new ArrayDeque>(); - stack.add(vertexData); - - while (!stack.isEmpty()) { - VertexData data = stack.removeLast(); - - if (!data.isDiscovered()) { - data.setDiscovered(true); - - if (vertices != null) { - vertices.add(data.getVertex()); - } - - stack.add(new VertexData1(data, true, true)); - - // follow all edges - for (E edge : visitedGraph.outgoingEdgesOf(data.getVertex())) { - VertexData targetData = - vertexToVertexData.get( - visitedGraph.getEdgeTarget(edge)); - - if (!targetData.isDiscovered()) { - // the "recursion" - stack.add(targetData); - } - } - } else if (data.isFinished()) { - if (vertices == null) { - orderedVertices.addFirst(data.getFinishedData()); - } - } - } - } - - /* - * Resets all VertexData objects. - */ - private void resetVertexData() - { - for (VertexData data : vertexToVertexData.values()) { - data.setDiscovered(false); - data.setFinished(false); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - /* - * Lightweight class storing some data for every vertex. - */ - private static abstract class VertexData - { - private byte bitfield; - - private VertexData( - boolean discovered, - boolean finished) - { - this.bitfield = 0; - setDiscovered(discovered); - setFinished(finished); - } - - private boolean isDiscovered() - { - if ((bitfield & 1) == 1) { - return true; - } - return false; - } - - private boolean isFinished() - { - if ((bitfield & 2) == 2) { - return true; - } - return false; - } - - private void setDiscovered(boolean discovered) - { - if (discovered) { - bitfield |= 1; - } else { - bitfield &= ~1; - } - } - - private void setFinished(boolean finished) - { - if (finished) { - bitfield |= 2; - } else { - bitfield &= ~2; - } - } - - abstract VertexData getFinishedData(); - - abstract V getVertex(); - } - - private static final class VertexData1 - extends VertexData - { - private final VertexData finishedData; - - private VertexData1( - VertexData finishedData, - boolean discovered, - boolean finished) - { - super(discovered, finished); - this.finishedData = finishedData; - } - - VertexData getFinishedData() - { - return finishedData; - } - - V getVertex() - { - return null; - } - } - - private static final class VertexData2 - extends VertexData - { - private final V vertex; - - private VertexData2( - V vertex, - boolean discovered, - boolean finished) - { - super(discovered, finished); - this.vertex = vertex; - } - - VertexData getFinishedData() - { - return null; - } - - V getVertex() - { - return vertex; - } - } -} - -// End StrongConnectivityInspector.java diff --git a/src/org/jgrapht/alg/TransitiveClosure.java b/src/org/jgrapht/alg/TransitiveClosure.java deleted file mode 100644 index 4f70b13..0000000 --- a/src/org/jgrapht/alg/TransitiveClosure.java +++ /dev/null @@ -1,138 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * TransitiveClosure.java - * ---------------------- - * (C) Copyright 2007, by Vinayak R. Borkar. - * - * Original Author: Vinayak R. Borkar - * Contributor(s): - * - * Changes - * ------- - * 5-May-2007: Initial revision (VRB); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.graph.*; - - -/** - * Constructs the transitive closure of the input graph. - * - * @author Vinayak R. Borkar - * @since May 5, 2007 - */ -public class TransitiveClosure -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Singleton instance. - */ - public static final TransitiveClosure INSTANCE = new TransitiveClosure(); - - //~ Constructors ----------------------------------------------------------- - - /** - * Private Constructor. - */ - private TransitiveClosure() - { - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Computes the transitive closure of the given graph. - * - * @param graph - Graph to compute transitive closure for. - */ - public void closeSimpleDirectedGraph(SimpleDirectedGraph graph) - { - Set vertexSet = graph.vertexSet(); - - Set newEdgeTargets = new HashSet(); - - // At every iteration of the outer loop, we add a path of length 1 - // between nodes that originally had a path of length 2. In the worst - // case, we need to make floor(log |V|) + 1 iterations. We stop earlier - // if there is no change to the output graph. - - int bound = computeBinaryLog(vertexSet.size()); - boolean done = false; - for (int i = 0; !done && (i < bound); ++i) { - done = true; - for (V v1 : vertexSet) { - newEdgeTargets.clear(); - - for (E v1OutEdge : graph.outgoingEdgesOf(v1)) { - V v2 = graph.getEdgeTarget(v1OutEdge); - for (E v2OutEdge : graph.outgoingEdgesOf(v2)) { - V v3 = graph.getEdgeTarget(v2OutEdge); - - if (v1.equals(v3)) { - // Its a simple graph, so no self loops. - continue; - } - - if (graph.getEdge(v1, v3) != null) { - // There is already an edge from v1 ---> v3, skip; - continue; - } - - newEdgeTargets.add(v3); - done = false; - } - } - - for (V v3 : newEdgeTargets) { - graph.addEdge(v1, v3); - } - } - } - } - - /** - * Computes floor(log_2(n)) + 1 - */ - private int computeBinaryLog(int n) - { - assert n >= 0; - - int result = 0; - while (n > 0) { - n >>= 1; - ++result; - } - - return result; - } -} - -// End TransitiveClosure.java diff --git a/src/org/jgrapht/alg/VertexCovers.java b/src/org/jgrapht/alg/VertexCovers.java deleted file mode 100644 index 71a5240..0000000 --- a/src/org/jgrapht/alg/VertexCovers.java +++ /dev/null @@ -1,157 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * VertexCovers.java - * ----------------- - * (C) Copyright 2003-2008, by Linda Buisman and Contributors. - * - * Original Author: Linda Buisman - * Contributor(s): Barak Naveh - * Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 06-Nov-2003 : Initial revision (LB); - * 07-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.alg.util.*; -import org.jgrapht.graph.*; - - -/** - * Algorithms to find a vertex cover for a graph. A vertex cover is a set of - * vertices that touches all the edges in the graph. The graph's vertex set is a - * trivial cover. However, a minimal vertex set (or at least an - * approximation for it) is usually desired. Finding a true minimal vertex cover - * is an NP-Complete problem. For more on the vertex cover problem, see - * http://mathworld.wolfram.com/VertexCover.html - * - * @author Linda Buisman - * @since Nov 6, 2003 - */ -public abstract class VertexCovers -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Finds a 2-approximation for a minimal vertex cover of the specified - * graph. The algorithm promises a cover that is at most double the size of - * a minimal cover. The algorithm takes O(|E|) time. - * - *

      For more details see Jenny Walter, CMPU-240: Lecture notes for - * Language Theory and Computation, Fall 2002, Vassar College, - * http://www.cs.vassar.edu/~walter/cs241index/lectures/PDF/approx.pdf. - *

      - * - * @param g the graph for which vertex cover approximation is to be found. - * - * @return a set of vertices which is a vertex cover for the specified - * graph. - */ - public static Set find2ApproximationCover(Graph g) - { - // C <-- {} - Set cover = new HashSet(); - - // G'=(V',E') <-- G(V,E) - Subgraph> sg = - new Subgraph>( - g, - null, - null); - - // while E' is non-empty - while (sg.edgeSet().size() > 0) { - // let (u,v) be an arbitrary edge of E' - E e = sg.edgeSet().iterator().next(); - - // C <-- C U {u,v} - V u = g.getEdgeSource(e); - V v = g.getEdgeTarget(e); - cover.add(u); - cover.add(v); - - // remove from E' every edge incident on either u or v - sg.removeVertex(u); - sg.removeVertex(v); - } - - return cover; // return C - } - - /** - * Finds a greedy approximation for a minimal vertex cover of a specified - * graph. At each iteration, the algorithm picks the vertex with the highest - * degree and adds it to the cover, until all edges are covered. - * - *

      The algorithm works on undirected graphs, but can also work on - * directed graphs when their edge-directions are ignored. To ignore edge - * directions you can use {@link org.jgrapht.Graphs#undirectedGraph(Graph)} - * or {@link org.jgrapht.graph.AsUndirectedGraph}.

      - * - * @param g the graph for which vertex cover approximation is to be found. - * - * @return a set of vertices which is a vertex cover for the specified - * graph. - */ - public static Set findGreedyCover(UndirectedGraph g) - { - // C <-- {} - Set cover = new HashSet(); - - // G' <-- G - UndirectedGraph sg = new UndirectedSubgraph(g, null, null); - - // compare vertices in descending order of degree - VertexDegreeComparator comp = - new VertexDegreeComparator(sg); - - // while G' != {} - while (sg.edgeSet().size() > 0) { - // v <-- vertex with maximum degree in G' - V v = Collections.max(sg.vertexSet(), comp); - - // C <-- C U {v} - cover.add(v); - - // remove from G' every edge incident on v, and v itself - sg.removeVertex(v); - } - - return cover; - } -} - -// End VertexCovers.java diff --git a/src/org/jgrapht/alg/package.html b/src/org/jgrapht/alg/package.html deleted file mode 100644 index 041cd4e..0000000 --- a/src/org/jgrapht/alg/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Algorithms provided with JGraphT. - - \ No newline at end of file diff --git a/src/org/jgrapht/alg/util/UnionFind.java b/src/org/jgrapht/alg/util/UnionFind.java deleted file mode 100644 index dcdb8aa..0000000 --- a/src/org/jgrapht/alg/util/UnionFind.java +++ /dev/null @@ -1,168 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * UnionFind.java - * ------------------------- - * (C) Copyright 2010-2010, by Tom Conerly and Contributors. - * - * Original Author: Tom Conerly - * Contributor(s): - * - * Changes - * ------- - * 02-Feb-2010 : Initial revision (TC); - * - */ -package org.jgrapht.alg.util; - -import java.util.*; - - -/** - * An implementation of Union - * Find data structure. Union Find is a disjoint-set data structure. It - * supports two operations: finding the set a specific element is in, and - * merging two sets. The implementation uses union by rank and path compression - * to achieve an amortized cost of O(a(n)) per operation where a is the inverse - * Ackermann function. UnionFind uses the hashCode and equals method of the - * elements it operates on. - * - * @author Tom Conerly - * @since Feb 10, 2010 - */ -public class UnionFind -{ - //~ Instance fields -------------------------------------------------------- - - private Map parentMap; - private Map rankMap; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a UnionFind instance with all of the elements of elements in - * seperate sets. - */ - public UnionFind(Set elements) - { - parentMap = new HashMap(); - rankMap = new HashMap(); - for (T element : elements) { - parentMap.put(element, element); - rankMap.put(element, 0); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Adds a new element to the data structure in its own set. - * - * @param element The element to add. - */ - public void addElement(T element) - { - parentMap.put(element, element); - rankMap.put(element, 0); - } - - /** - * @return map from element to parent element - */ - protected Map getParentMap() - { - return parentMap; - } - - /** - * @return map from element to rank - */ - protected Map getRankMap() - { - return rankMap; - } - - /** - * Returns the representative element of the set that element is in. - * - * @param element The element to find. - * - * @return The element representing the set the element is in. - */ - public T find(T element) - { - if (!parentMap.containsKey(element)) { - throw new IllegalArgumentException( - "elements must be contained in given set"); - } - - T parent = parentMap.get(element); - if (parent.equals(element)) { - return element; - } - - T newParent = find(parent); - parentMap.put(element, newParent); - return newParent; - } - - /** - * Merges the sets which contain element1 and element2. - * - * @param element1 The first element to union. - * @param element2 The second element to union. - */ - public void union(T element1, T element2) - { - if (!parentMap.containsKey(element1) - || !parentMap.containsKey(element2)) - { - throw new IllegalArgumentException( - "elements must be contained in given set"); - } - - T parent1 = find(element1); - T parent2 = find(element2); - - //check if the elements are already in the same set - if (parent1.equals(parent2)) { - return; - } - - int rank1 = rankMap.get(parent1); - int rank2 = rankMap.get(parent2); - if (rank1 > rank2) { - parentMap.put(parent2, parent1); - } else if (rank1 < rank2) { - parentMap.put(parent1, parent2); - } else { - parentMap.put(parent2, parent1); - rankMap.put(parent1, rank1 + 1); - } - } -} - -// End UnionFind.java diff --git a/src/org/jgrapht/alg/util/VertexDegreeComparator.java b/src/org/jgrapht/alg/util/VertexDegreeComparator.java deleted file mode 100644 index a09d615..0000000 --- a/src/org/jgrapht/alg/util/VertexDegreeComparator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------------- - * VertexDegreeComparator.java - * --------------------------- - * (C) Copyright 2003-2008, by Linda Buisman and Contributors. - * - * Original Author: Linda Buisman - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 06-Nov-2003 : Initial revision (LB); - * 07-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.alg.util; - -import org.jgrapht.*; - - -/** - * Compares two vertices based on their degree. - * - *

      Used by greedy algorithms that need to sort vertices by their degree. Two - * vertices are considered equal if their degrees are equal.

      - * - * @author Linda Buisman - * @since Nov 6, 2003 - */ -public class VertexDegreeComparator - implements java.util.Comparator -{ - //~ Instance fields -------------------------------------------------------- - - /** - * The graph that contains the vertices to be compared. - */ - private UndirectedGraph graph; - - /** - * The sort order for vertex degree. true for ascending degree - * order (smaller degrees first), false for descending. - */ - private boolean ascendingOrder; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a comparator for comparing the degrees of vertices in the - * specified graph. The comparator compares in ascending order of degrees - * (lowest first). - * - * @param g graph with respect to which the degree is calculated. - */ - public VertexDegreeComparator(UndirectedGraph g) - { - this(g, true); - } - - /** - * Creates a comparator for comparing the degrees of vertices in the - * specified graph. - * - * @param g graph with respect to which the degree is calculated. - * @param ascendingOrder true - compares in ascending order of degrees - * (lowest first), false - compares in descending order of degrees (highest - * first). - */ - public VertexDegreeComparator( - UndirectedGraph g, - boolean ascendingOrder) - { - graph = g; - this.ascendingOrder = ascendingOrder; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Compare the degrees of v1 and v2, taking into - * account whether ascending or descending order is used. - * - * @param v1 the first vertex to be compared. - * @param v2 the second vertex to be compared. - * - * @return -1 if v1 comes before v2, +1 if - * v1 comes after v2, 0 if equal. - */ - public int compare(V v1, V v2) - { - int degree1 = graph.degreeOf(v1); - int degree2 = graph.degreeOf(v2); - - if (((degree1 < degree2) && ascendingOrder) - || ((degree1 > degree2) && !ascendingOrder)) - { - return -1; - } else if ( - ((degree1 > degree2) && ascendingOrder) - || ((degree1 < degree2) && !ascendingOrder)) - { - return 1; - } else { - return 0; - } - } -} - -// End VertexDegreeComparator.java diff --git a/src/org/jgrapht/alg/util/package.html b/src/org/jgrapht/alg/util/package.html deleted file mode 100644 index 38c56f6..0000000 --- a/src/org/jgrapht/alg/util/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Utilities used by JGraphT algorithms. - - diff --git a/src/org/jgrapht/event/ConnectedComponentTraversalEvent.java b/src/org/jgrapht/event/ConnectedComponentTraversalEvent.java deleted file mode 100644 index 134be60..0000000 --- a/src/org/jgrapht/event/ConnectedComponentTraversalEvent.java +++ /dev/null @@ -1,103 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------------- - * ConnectedComponentTraversalEvent.java - * ------------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): - - * - * $Id: ConnectedComponentTraversalEvent.java 487 2006-07-02 00:53:17Z - * perfecthash $ - * - * Changes - * ------- - * 11-Aug-2003 : Initial revision (BN); - * - */ -package org.jgrapht.event; - -import java.util.*; - - -/** - * A traversal event with respect to a connected component. - * - * @author Barak Naveh - * @since Aug 11, 2003 - */ -public class ConnectedComponentTraversalEvent - extends EventObject -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3834311717709822262L; - - /** - * Connected component traversal started event. - */ - public static final int CONNECTED_COMPONENT_STARTED = 31; - - /** - * Connected component traversal finished event. - */ - public static final int CONNECTED_COMPONENT_FINISHED = 32; - - //~ Instance fields -------------------------------------------------------- - - /** - * The type of this event. - */ - private int type; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new ConnectedComponentTraversalEvent. - * - * @param eventSource the source of the event. - * @param type the type of event. - */ - public ConnectedComponentTraversalEvent(Object eventSource, int type) - { - super(eventSource); - this.type = type; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the event type. - * - * @return the event type. - */ - public int getType() - { - return type; - } -} - -// End ConnectedComponentTraversalEvent.java diff --git a/src/org/jgrapht/event/EdgeTraversalEvent.java b/src/org/jgrapht/event/EdgeTraversalEvent.java deleted file mode 100644 index 4cd33ed..0000000 --- a/src/org/jgrapht/event/EdgeTraversalEvent.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------- - * EdgeTraversalEvent.java - * ----------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 11-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -import java.util.*; - - -/** - * A traversal event for a graph edge. - * - * @author Barak Naveh - * @since Aug 11, 2003 - */ -public class EdgeTraversalEvent - extends EventObject -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 4050768173789820979L; - - //~ Instance fields -------------------------------------------------------- - - /** - * The traversed edge. - */ - protected E edge; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new EdgeTraversalEvent. - * - * @param eventSource the source of the event. - * @param edge the traversed edge. - */ - public EdgeTraversalEvent(Object eventSource, E edge) - { - super(eventSource); - this.edge = edge; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the traversed edge. - * - * @return the traversed edge. - */ - public E getEdge() - { - return edge; - } -} - -// End EdgeTraversalEvent.java diff --git a/src/org/jgrapht/event/GraphChangeEvent.java b/src/org/jgrapht/event/GraphChangeEvent.java deleted file mode 100644 index 7b0a6a9..0000000 --- a/src/org/jgrapht/event/GraphChangeEvent.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------- - * GraphChangeEvent.java - * --------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 10-Aug-2003 : Initial revision (BN); - * - */ -package org.jgrapht.event; - -import java.util.*; - - -/** - * An event which indicates that a graph has changed. This class is a root for - * graph change events. - * - * @author Barak Naveh - * @since Aug 10, 2003 - */ -public class GraphChangeEvent - extends EventObject -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3834592106026382391L; - - //~ Instance fields -------------------------------------------------------- - - /** - * The type of graph change this event indicates. - */ - protected int type; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new graph change event. - * - * @param eventSource the source of the event. - * @param type the type of event. - */ - public GraphChangeEvent(Object eventSource, int type) - { - super(eventSource); - this.type = type; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the event type. - * - * @return the event type. - */ - public int getType() - { - return type; - } -} - -// End GraphChangeEvent.java diff --git a/src/org/jgrapht/event/GraphEdgeChangeEvent.java b/src/org/jgrapht/event/GraphEdgeChangeEvent.java deleted file mode 100644 index bfe47c0..0000000 --- a/src/org/jgrapht/event/GraphEdgeChangeEvent.java +++ /dev/null @@ -1,169 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * GraphEdgeChangeEvent.java - * ------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 10-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -/** - * An event which indicates that a graph edge has changed, or is about to - * change. The event can be used either as an indication after the edge - * has been added or removed, or before it is added. The type of the - * event can be tested using the {@link - * org.jgrapht.event.GraphChangeEvent#getType()} method. - * - * @author Barak Naveh - * @since Aug 10, 2003 - */ -public class GraphEdgeChangeEvent - extends GraphChangeEvent -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3618134563335844662L; - - /** - * Before edge added event. This event is fired before an edge is added to a - * graph. - */ - public static final int BEFORE_EDGE_ADDED = 21; - - /** - * Before edge removed event. This event is fired before an edge is removed - * from a graph. - */ - public static final int BEFORE_EDGE_REMOVED = 22; - - /** - * Edge added event. This event is fired after an edge is added to a graph. - */ - public static final int EDGE_ADDED = 23; - - /** - * Edge removed event. This event is fired after an edge is removed from a - * graph. - */ - public static final int EDGE_REMOVED = 24; - - //~ Instance fields -------------------------------------------------------- - - /** - * The edge that this event is related to. - */ - protected E edge; - - /** - * The source vertex of the edge that this event is related to. - */ - protected V edgeSource; - - /** - * The target vertex of the edge that this event is related to. - */ - protected V edgeTarget; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for GraphEdgeChangeEvent. - * - * @param eventSource the source of this event. - * @param type the event type of this event. - * @param edge the edge that this event is related to. - * - * @deprecated Use new constructor which takes vertex parameters. - */ - public GraphEdgeChangeEvent( - Object eventSource, int type, E edge) - { - this(eventSource, type, edge, null, null); - } - - /** - * Constructor for GraphEdgeChangeEvent. - * - * @param eventSource the source of this event. - * @param type the event type of this event. - * @param edge the edge that this event is related to. - * @param edgeSource edge source vertex - * @param edgeTarget edge target vertex - */ - public GraphEdgeChangeEvent( - Object eventSource, int type, E edge, - V edgeSource, V edgeTarget) - { - super(eventSource, type); - this.edge = edge; - this.edgeSource = edgeSource; - this.edgeTarget = edgeTarget; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the edge that this event is related to. - * - * @return event edge - */ - public E getEdge() - { - return edge; - } - - /** - * Returns the source vertex that this event is related to. - * - * @return event source vertex - */ - public V getEdgeSource() - { - return edgeSource; - } - - /** - * Returns the target vertex that this event is related to. - * - * @return event target vertex - */ - public V getEdgeTarget() - { - return edgeTarget; - } -} - -// End GraphEdgeChangeEvent.java diff --git a/src/org/jgrapht/event/GraphListener.java b/src/org/jgrapht/event/GraphListener.java deleted file mode 100644 index fb185c0..0000000 --- a/src/org/jgrapht/event/GraphListener.java +++ /dev/null @@ -1,74 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * GraphListener.java - * ------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -/** - * A listener that is notified when the graph changes. - * - *

      If only notifications on vertex set changes are required it is more - * efficient to use the VertexSetListener.

      - * - * @author Barak Naveh - * @see VertexSetListener - * @since Jul 18, 2003 - */ -public interface GraphListener - extends VertexSetListener -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Notifies that an edge has been added to the graph. - * - * @param e the edge event. - */ - public void edgeAdded(GraphEdgeChangeEvent e); - - /** - * Notifies that an edge has been removed from the graph. - * - * @param e the edge event. - */ - public void edgeRemoved(GraphEdgeChangeEvent e); -} - -// End GraphListener.java diff --git a/src/org/jgrapht/event/GraphVertexChangeEvent.java b/src/org/jgrapht/event/GraphVertexChangeEvent.java deleted file mode 100644 index 7c7dd11..0000000 --- a/src/org/jgrapht/event/GraphVertexChangeEvent.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------------- - * GraphVertexChangeEvent.java - * --------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 10-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -/** - * An event which indicates that a graph vertex has changed, or is about to - * change. The event can be used either as an indication after the vertex - * has been added or removed, or before it is added. The type of the - * event can be tested using the {@link - * org.jgrapht.event.GraphChangeEvent#getType()} method. - * - * @author Barak Naveh - * @since Aug 10, 2003 - */ -public class GraphVertexChangeEvent - extends GraphChangeEvent -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3690189962679104053L; - - /** - * Before vertex added event. This event is fired before a vertex is added - * to a graph. - */ - public static final int BEFORE_VERTEX_ADDED = 11; - - /** - * Before vertex removed event. This event is fired before a vertex is - * removed from a graph. - */ - public static final int BEFORE_VERTEX_REMOVED = 12; - - /** - * Vertex added event. This event is fired after a vertex is added to a - * graph. - */ - public static final int VERTEX_ADDED = 13; - - /** - * Vertex removed event. This event is fired after a vertex is removed from - * a graph. - */ - public static final int VERTEX_REMOVED = 14; - - //~ Instance fields -------------------------------------------------------- - - /** - * The vertex that this event is related to. - */ - protected V vertex; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new GraphVertexChangeEvent object. - * - * @param eventSource the source of the event. - * @param type the type of the event. - * @param vertex the vertex that the event is related to. - */ - public GraphVertexChangeEvent(Object eventSource, int type, V vertex) - { - super(eventSource, type); - this.vertex = vertex; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the vertex that this event is related to. - * - * @return the vertex that this event is related to. - */ - public V getVertex() - { - return vertex; - } -} - -// End GraphVertexChangeEvent.java diff --git a/src/org/jgrapht/event/TraversalListener.java b/src/org/jgrapht/event/TraversalListener.java deleted file mode 100644 index 605848e..0000000 --- a/src/org/jgrapht/event/TraversalListener.java +++ /dev/null @@ -1,100 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * TraversalListener.java - * ---------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Aug-2003 : Adaptation to new event model (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -/** - * A listener on graph iterator or on a graph traverser. - * - * @author Barak Naveh - * @since Jul 19, 2003 - */ -public interface TraversalListener -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Called to inform listeners that the traversal of the current connected - * component has finished. - * - * @param e the traversal event. - */ - public void connectedComponentFinished( - ConnectedComponentTraversalEvent e); - - /** - * Called to inform listeners that a traversal of a new connected component - * has started. - * - * @param e the traversal event. - */ - public void connectedComponentStarted(ConnectedComponentTraversalEvent e); - - /** - * Called to inform the listener that the specified edge have been visited - * during the graph traversal. Depending on the traversal algorithm, edge - * might be visited more than once. - * - * @param e the edge traversal event. - */ - public void edgeTraversed(EdgeTraversalEvent e); - - /** - * Called to inform the listener that the specified vertex have been visited - * during the graph traversal. Depending on the traversal algorithm, vertex - * might be visited more than once. - * - * @param e the vertex traversal event. - */ - public void vertexTraversed(VertexTraversalEvent e); - - /** - * Called to inform the listener that the specified vertex have been - * finished during the graph traversal. Exact meaning of "finish" is - * algorithm-dependent; e.g. for DFS, it means that all vertices reachable - * via the vertex have been visited as well. - * - * @param e the vertex traversal event. - */ - public void vertexFinished(VertexTraversalEvent e); -} - -// End TraversalListener.java diff --git a/src/org/jgrapht/event/TraversalListenerAdapter.java b/src/org/jgrapht/event/TraversalListenerAdapter.java deleted file mode 100644 index a4985e0..0000000 --- a/src/org/jgrapht/event/TraversalListenerAdapter.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------------- - * TraversalListenerAdapter.java - * ----------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 06-Aug-2003 : Initial revision (BN); - * 11-Aug-2003 : Adaptation to new event model (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -/** - * An empty do-nothing implementation of the {@link TraversalListener} interface - * used for subclasses. - * - * @author Barak Naveh - * @since Aug 6, 2003 - */ -public class TraversalListenerAdapter - implements TraversalListener -{ - //~ Methods ---------------------------------------------------------------- - - /** - * @see TraversalListener#connectedComponentFinished(ConnectedComponentTraversalEvent) - */ - public void connectedComponentFinished( - ConnectedComponentTraversalEvent e) - { - } - - /** - * @see TraversalListener#connectedComponentStarted(ConnectedComponentTraversalEvent) - */ - public void connectedComponentStarted(ConnectedComponentTraversalEvent e) - { - } - - /** - * @see TraversalListener#edgeTraversed(EdgeTraversalEvent) - */ - public void edgeTraversed(EdgeTraversalEvent e) - { - } - - /** - * @see TraversalListener#vertexTraversed(VertexTraversalEvent) - */ - public void vertexTraversed(VertexTraversalEvent e) - { - } - - /** - * @see TraversalListener#vertexFinished(VertexTraversalEvent) - */ - public void vertexFinished(VertexTraversalEvent e) - { - } -} - -// End TraversalListenerAdapter.java diff --git a/src/org/jgrapht/event/VertexSetListener.java b/src/org/jgrapht/event/VertexSetListener.java deleted file mode 100644 index c0dd692..0000000 --- a/src/org/jgrapht/event/VertexSetListener.java +++ /dev/null @@ -1,77 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * VertexSetListener.java - * ---------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -import java.util.*; - - -/** - * A listener that is notified when the graph's vertex set changes. It should be - * used when only notifications on vertex-set changes are of interest. If - * all graph notifications are of interest better use - * GraphListener. - * - * @author Barak Naveh - * @see GraphListener - * @since Jul 18, 2003 - */ -public interface VertexSetListener - extends EventListener -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Notifies that a vertex has been added to the graph. - * - * @param e the vertex event. - */ - public void vertexAdded(GraphVertexChangeEvent e); - - /** - * Notifies that a vertex has been removed from the graph. - * - * @param e the vertex event. - */ - public void vertexRemoved(GraphVertexChangeEvent e); -} - -// End VertexSetListener.java diff --git a/src/org/jgrapht/event/VertexTraversalEvent.java b/src/org/jgrapht/event/VertexTraversalEvent.java deleted file mode 100644 index c72e927..0000000 --- a/src/org/jgrapht/event/VertexTraversalEvent.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * VertexTraversalEvent.java - * ------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 11-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.event; - -import java.util.*; - - -/** - * A traversal event for a graph vertex. - * - * @author Barak Naveh - * @since Aug 11, 2003 - */ -public class VertexTraversalEvent - extends EventObject -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3688790267213918768L; - - //~ Instance fields -------------------------------------------------------- - - /** - * The traversed vertex. - */ - protected V vertex; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new VertexTraversalEvent. - * - * @param eventSource the source of the event. - * @param vertex the traversed vertex. - */ - public VertexTraversalEvent(Object eventSource, V vertex) - { - super(eventSource); - this.vertex = vertex; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the traversed vertex. - * - * @return the traversed vertex. - */ - public V getVertex() - { - return vertex; - } -} - -// End VertexTraversalEvent.java diff --git a/src/org/jgrapht/event/package.html b/src/org/jgrapht/event/package.html deleted file mode 100644 index 9a0bf09..0000000 --- a/src/org/jgrapht/event/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - -Event classes and listener interfaces, used to provide a change -notification mechanism on graph modification events. - - diff --git a/src/org/jgrapht/experimental/GraphReader.java b/src/org/jgrapht/experimental/GraphReader.java deleted file mode 100644 index 0bee22e..0000000 --- a/src/org/jgrapht/experimental/GraphReader.java +++ /dev/null @@ -1,181 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * GraphReader.java - * ------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (BN); - * - */ -package org.jgrapht.experimental; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.generate.*; - - -public class GraphReader - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - // ~ Static fields/initializers -------------------------------------------- - - // ~ Instance fields ------------------------------------------------------- - - // ~ Static fields/initializers -------------------------------------------- - - // ~ Instance fields ------------------------------------------------------- - - private final BufferedReader _in; - private final boolean _isWeighted; - private final double _defaultWeight; - - // ~ Constructors ---------------------------------------------------------- - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new GraphReader. - */ - private GraphReader(Reader input, boolean isWeighted, double defaultWeight) - throws IOException - { - if (input instanceof BufferedReader) { - _in = (BufferedReader) input; - } else { - _in = new BufferedReader(input); - } - _isWeighted = isWeighted; - _defaultWeight = defaultWeight; - } - - /** - * Construct a new GraphReader. - */ - public GraphReader(Reader input) - throws IOException - { - this(input, false, 1); - } - - /** - * Construct a new GraphReader. - */ - public GraphReader(Reader input, double defaultWeight) - throws IOException - { - this(input, true, defaultWeight); - } - - //~ Methods ---------------------------------------------------------------- - - // ~ Methods --------------------------------------------------------------- - - private String [] split(final String src) - { - if (src == null) { - return null; - } - return src.split("\\s+"); - } - - private String [] skipComments() - { - String [] cols = null; - try { - cols = split(_in.readLine()); - while ( - (cols != null) - && ((cols.length == 0) - || cols[0].equals("c") - || cols[0].startsWith("%"))) - { - cols = split(_in.readLine()); - } - } catch (IOException e) { - } - return cols; - } - - private int readNodeCount() - { - final String [] cols = skipComments(); - if (cols[0].equals("p")) { - return Integer.parseInt(cols[1]); - } - return -1; - } - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - final int size = readNodeCount(); - if (resultMap == null) { - resultMap = new HashMap(); - } - - for (int i = 0; i < size; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - resultMap.put(Integer.toString(i + 1), newVertex); - } - String [] cols = skipComments(); - while (cols != null) { - if (cols[0].equals("e")) { - E edge = - target.addEdge( - resultMap.get(cols[1]), - resultMap.get(cols[2])); - if (_isWeighted && (edge != null)) { - double weight = _defaultWeight; - if (cols.length > 3) { - weight = Double.parseDouble(cols[3]); - } - ((WeightedGraph) target).setEdgeWeight(edge, weight); - } - } - cols = skipComments(); - } - } -} - -// End GraphReader.java diff --git a/src/org/jgrapht/experimental/GraphSquare.java b/src/org/jgrapht/experimental/GraphSquare.java deleted file mode 100644 index 4d10c73..0000000 --- a/src/org/jgrapht/experimental/GraphSquare.java +++ /dev/null @@ -1,219 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * GraphSquare.java - * ---------------------- - * (C) Copyright 2004-2008, by Michael Behrisch and Contributors. - * - * Original Author: Michael Behrisch - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 14-Sep-2004 : Initial revision (MB); - * - */ -package org.jgrapht.experimental; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; -import org.jgrapht.graph.*; - - -/** - * DOCUMENT ME! - * - * @author Michael Behrisch - * @since Sep 14, 2004 - */ -public class GraphSquare - extends AbstractBaseGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -2642034600395594304L; - private static final String UNMODIFIABLE = "this graph is unmodifiable"; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for GraphSquare. - * - * @param g the graph of which a square is to be created. - * @param createLoops - */ - public GraphSquare(final Graph g, final boolean createLoops) - { - super(g.getEdgeFactory(), false, createLoops); - Graphs.addAllVertices(this, g.vertexSet()); - addSquareEdges(g, createLoops); - - if (g instanceof ListenableGraph) { - ((ListenableGraph) g).addGraphListener( - new GraphListener() { - public void edgeAdded(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - addEdgesStartingAt( - g, - g.getEdgeSource(edge), - g.getEdgeTarget(edge), - createLoops); - addEdgesStartingAt( - g, - g.getEdgeTarget(edge), - g.getEdgeSource(edge), - createLoops); - } - - public void edgeRemoved(GraphEdgeChangeEvent e) - { // this is not a very performant implementation - GraphSquare.super.removeAllEdges(edgeSet()); - addSquareEdges(g, createLoops); - } - - public void vertexAdded(GraphVertexChangeEvent e) - { - } - - public void vertexRemoved(GraphVertexChangeEvent e) - { - } - }); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#addEdge(Object, Object, E) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllEdges(Collection) - */ - public boolean removeAllEdges(Collection edges) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllEdges(V, V) - */ - public Set removeAllEdges(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllVertices(Collection) - */ - public boolean removeAllVertices(Collection vertices) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(E) - */ - public boolean removeEdge(E e) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(V, V) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeVertex(V) - */ - public boolean removeVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - private void addEdgesStartingAt( - final Graph g, - final V v, - final V u, - boolean createLoops) - { - if (!g.containsEdge(v, u)) { - return; - } - - final List adjVertices = Graphs.neighborListOf(g, u); - - for (int i = 0; i < adjVertices.size(); i++) { - final V w = adjVertices.get(i); - - if (g.containsEdge(u, w) && ((v != w) || createLoops)) { - super.addEdge(v, w); - } - } - } - - private void addSquareEdges(Graph g, boolean createLoops) - { - for (V v : g.vertexSet()) { - List adjVertices = Graphs.neighborListOf(g, v); - - for (int i = 0; i < adjVertices.size(); i++) { - addEdgesStartingAt(g, v, adjVertices.get(i), createLoops); - } - } - } -} - -// End GraphSquare.java diff --git a/src/org/jgrapht/experimental/GraphTests.java b/src/org/jgrapht/experimental/GraphTests.java deleted file mode 100644 index 8c099e1..0000000 --- a/src/org/jgrapht/experimental/GraphTests.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.jgrapht.experimental; - -import java.util.*; - -import org.jgrapht.*; - - -public final class GraphTests -{ - //~ Constructors ----------------------------------------------------------- - - private GraphTests() - { - } - - //~ Methods ---------------------------------------------------------------- - - public static boolean isEmpty(Graph g) - { - return g.edgeSet().isEmpty(); - } - - public static boolean isComplete(Graph g) - { - int n = g.vertexSet().size(); - return g.edgeSet().size() - == (n * (n - 1) / 2); - } - - public static boolean isConnected(Graph g) - { - int numVertices = g.vertexSet().size(); - int numEdges = g.edgeSet().size(); - - if (numEdges < (numVertices - 1)) { - return false; - } - if ((numVertices < 2) - || (numEdges > ((numVertices - 1) * (numVertices - 2) / 2))) - { - return true; - } - - Set known = new HashSet(); - LinkedList queue = new LinkedList(); - V v = g.vertexSet().iterator().next(); - - queue.add(v); // start with node 1 - known.add(v); - - while (!queue.isEmpty()) { - v = queue.removeFirst(); - for ( - Iterator it = Graphs.neighborListOf(g, v).iterator(); - it.hasNext();) - { - v = it.next(); - if (!known.contains(v)) { - known.add(v); - queue.add(v); - } - } - } - return known.size() == numVertices; - } - - public static boolean isTree(Graph g) - { - return isConnected(g) - && (g.edgeSet().size() == (g.vertexSet().size() - 1)); - } - - public static boolean isBipartite(Graph g) - { - if ((4 * g.edgeSet().size()) - > (g.vertexSet().size() * g.vertexSet().size())) - { - return false; - } - if (isEmpty(g)) { - return true; - } - - Set unknown = new HashSet(g.vertexSet()); - LinkedList queue = new LinkedList(); - V v = unknown.iterator().next(); - Set odd = new HashSet(); - - queue.add(v); - - while (!unknown.isEmpty()) { - if (queue.isEmpty()) { - queue.add(unknown.iterator().next()); - } - - v = queue.removeFirst(); - unknown.remove(v); - - for ( - Iterator it = Graphs.neighborListOf(g, v).iterator(); - it.hasNext();) - { - V n = it.next(); - if (unknown.contains(n)) { - queue.add(n); - if (!odd.contains(v)) { - odd.add(n); - } - } else if (!(odd.contains(v) ^ odd.contains(n))) { - return false; - } - } - } - return true; - } -} - -// End GraphTests.java diff --git a/src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java b/src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java deleted file mode 100644 index 0f9981b..0000000 --- a/src/org/jgrapht/experimental/PartiteRandomGraphGenerator.java +++ /dev/null @@ -1,171 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * PartiteRandomGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. - * - * Original Author: Michael Behrisch - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 13-Sep-2004 : Initial revision (MB); - * - */ -// package org.jgrapht.generate; -package org.jgrapht.experimental; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.generate.*; - - -/** - * PartiteRandomGraphGenerator generates a partite uniform random - * graph of any size. A partite uniform random graph contains edges chosen - * independently uniformly at random from the set of possible edges between - * partition classes. - * - * @author Michael Behrisch - * @since Sep 13, 2004 - */ -public class PartiteRandomGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private final int [] numVertices; - private final int numEdges; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new PartiteRandomGraphGenerator for a bipartite graph. - * - * @param numVertices1 number of vertices in the first partition - * @param numVertices2 number of vertices in the second partition - * @param numEdges number of edges to be generated - * - * @throws IllegalArgumentException - */ - public PartiteRandomGraphGenerator( - int numVertices1, - int numVertices2, - int numEdges) - { - if ((numVertices1 < 0) || (numVertices2 < 0)) { - throw new IllegalArgumentException("must be non-negative"); - } - - if ((numEdges < 0) || (numEdges > (numVertices1 * numVertices2))) { - throw new IllegalArgumentException("illegal number of edges"); - } - - final int [] numVertices = { - numVertices1, - numVertices2 - }; - this.numVertices = numVertices; - this.numEdges = numEdges; - } - - /** - * Construct a new PartiteRandomGraphGenerator for a k-partite graph. - * - * @param numVertices number of vertices in the k partitions - * @param numEdges number of edges to be generated between any two - * partitions - * - * @throws IllegalArgumentException - */ - public PartiteRandomGraphGenerator(int [] numVertices, int numEdges) - { - if (numEdges < 0) { - throw new IllegalArgumentException("illegal number of edges"); - } - - for (int i = 0; i < numVertices.length; i++) { - if (numVertices[i] < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - for (int j = 0; j < i; j++) { - if (numEdges > (numVertices[i] * numVertices[j])) { - throw new IllegalArgumentException( - "illegal number of edges"); - } - } - } - - this.numVertices = numVertices; - this.numEdges = numEdges; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * TODO hb 30-nov-05: document me - * - * @param target - * @param vertexFactory - * @param resultMap some array of vertices - * - * @see GraphGenerator#generateGraph - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - Object [][] vertices = new Object[numVertices.length][]; - - for (int i = 0; i < numVertices.length; i++) { - vertices[i] = - RandomGraphHelper.addVertices( - target, - vertexFactory, - numVertices[i]); - - if (resultMap != null) { - resultMap.put(Integer.toString(i), vertices[i]); - } - - for (int j = 0; j < i; j++) { - RandomGraphHelper.addEdges( - target, - Arrays.asList(vertices[i]), - Arrays.asList(vertices[j]), - numEdges); - } - } - } -} - -// End PartiteRandomGraphGenerator.java diff --git a/src/org/jgrapht/experimental/RandomGraphHelper.java b/src/org/jgrapht/experimental/RandomGraphHelper.java deleted file mode 100644 index 731f9e5..0000000 --- a/src/org/jgrapht/experimental/RandomGraphHelper.java +++ /dev/null @@ -1,126 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * RandomGraphHelper.java - * ------------------- - * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. - * - * Original Author: Michael Behrisch - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 13-Sep-2004 : Initial revision (MB); - * - */ -// package org.jgrapht.generate; -package org.jgrapht.experimental; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * UniformRandomGraphGenerator generates a uniform random graph - * of any size. A uniform random graph contains edges chosen independently - * uniformly at random from the set of all possible edges. - * - * @author Michael Behrisch - * @since Sep 13, 2004 - */ -public final class RandomGraphHelper -{ - //~ Static fields/initializers --------------------------------------------- - - private static final Random randSingleton = new Random(); - - //~ Constructors ----------------------------------------------------------- - - /** - * . - */ - private RandomGraphHelper() - { - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see GraphGenerator#generateGraph - */ - @SuppressWarnings("unchecked") - public static void addEdges( - Graph target, - List sourceVertices, - List destVertices, - int numEdges) - { - int sourceSize = sourceVertices.size(); - int destSize = destVertices.size(); - - for (int i = 0; i < numEdges; ++i) { - while ( - target.addEdge( - sourceVertices.get(randSingleton.nextInt( - sourceSize)), - destVertices.get(randSingleton.nextInt(destSize))) - == null) - { - ; - } - } - } - - /** - * . - * - * @param target - * @param vertexFactory - * @param numVertices - * - * @return - */ - @SuppressWarnings("unchecked") - public static Object [] addVertices( - Graph target, - VertexFactory vertexFactory, - int numVertices) - { - Object [] vertices = new Object[numVertices]; - - for (int i = 0; i < numVertices; ++i) { - vertices[i] = vertexFactory.createVertex(); - target.addVertex(vertices[i]); - } - - return vertices; - } -} - -// End RandomGraphHelper.java diff --git a/src/org/jgrapht/experimental/UniformRandomGraphGenerator.java b/src/org/jgrapht/experimental/UniformRandomGraphGenerator.java deleted file mode 100644 index 6b34839..0000000 --- a/src/org/jgrapht/experimental/UniformRandomGraphGenerator.java +++ /dev/null @@ -1,115 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * UniformRandomGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by Michael Behrisch and Contributors. - * - * Original Author: Michael Behrisch - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 13-Sep-2004 : Initial revision (MB); - * - */ -// package org.jgrapht.generate; -package org.jgrapht.experimental; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.generate.*; - - -/** - * UniformRandomGraphGenerator generates a uniform random graph - * of any size. A uniform random graph contains edges chosen independently - * uniformly at random from the set of all possible edges. - * - * @author Michael Behrisch - * @since Sep 13, 2004 - */ -public class UniformRandomGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private final int numEdges; - private final int numVertices; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new UniformRandomGraphGenerator. - * - * @param numVertices number of vertices to be generated - * @param numEdges number of edges to be generated - * - * @throws IllegalArgumentException - */ - public UniformRandomGraphGenerator(int numVertices, int numEdges) - { - if (numVertices < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - if ((numEdges < 0) - || (numEdges > (numVertices * (numVertices - 1) / 2))) - { - throw new IllegalArgumentException("illegal number of edges"); - } - - this.numVertices = numVertices; - this.numEdges = numEdges; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see GraphGenerator#generateGraph - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - Object [] vertices = - RandomGraphHelper.addVertices( - target, - vertexFactory, - numVertices); - RandomGraphHelper.addEdges( - target, - Arrays.asList(vertices), - Arrays.asList(vertices), - numEdges); - } -} - -// End UniformRandomGraphGenerator.java diff --git a/src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java b/src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java deleted file mode 100644 index d366996..0000000 --- a/src/org/jgrapht/experimental/alg/ApproximationAlgorithm.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.jgrapht.experimental.alg; - -import java.util.*; - - -public interface ApproximationAlgorithm -{ - //~ Methods ---------------------------------------------------------------- - - ResultType getUpperBound(Map optionalData); - - ResultType getLowerBound(Map optionalData); - - boolean isExact(); -} - -// End ApproximationAlgorithm.java diff --git a/src/org/jgrapht/experimental/alg/ExactAlgorithm.java b/src/org/jgrapht/experimental/alg/ExactAlgorithm.java deleted file mode 100644 index a3a4a2e..0000000 --- a/src/org/jgrapht/experimental/alg/ExactAlgorithm.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jgrapht.experimental.alg; - -import java.util.*; - - -public interface ExactAlgorithm -{ - //~ Methods ---------------------------------------------------------------- - - ResultType getResult(Map optionalData); -} - -// End ExactAlgorithm.java diff --git a/src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java b/src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java deleted file mode 100644 index fdcbc5c..0000000 --- a/src/org/jgrapht/experimental/alg/IntArrayGraphAlgorithm.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * - */ -package org.jgrapht.experimental.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * @author micha - */ -public abstract class IntArrayGraphAlgorithm -{ - //~ Instance fields -------------------------------------------------------- - - protected final List _vertices; - protected final int [][] _neighbors; - protected final Map _vertexToPos; - - //~ Constructors ----------------------------------------------------------- - - /** - * @param g - */ - public IntArrayGraphAlgorithm(final Graph g) - { - final int numVertices = g.vertexSet().size(); - _vertices = new ArrayList(numVertices); - _neighbors = new int[numVertices][]; - _vertexToPos = new HashMap(numVertices); - for (V vertex : g.vertexSet()) { - _neighbors[_vertices.size()] = new int[g.edgesOf(vertex).size()]; - _vertexToPos.put(vertex, _vertices.size()); - _vertices.add(vertex); - } - for (int i = 0; i < numVertices; i++) { - int nbIndex = 0; - final V vertex = _vertices.get(i); - for (E e : g.edgesOf(vertex)) { - _neighbors[i][nbIndex++] = - _vertexToPos.get(Graphs.getOppositeVertex(g, e, vertex)); - } - } - } -} - -// End IntArrayGraphAlgorithm.java diff --git a/src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java b/src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java deleted file mode 100644 index dfa66f9..0000000 --- a/src/org/jgrapht/experimental/alg/color/BrownBacktrackColoring.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * - */ -package org.jgrapht.experimental.alg.color; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.experimental.alg.*; - - -/** - * @author micha - */ -public class BrownBacktrackColoring - extends IntArrayGraphAlgorithm - implements ExactAlgorithm -{ - //~ Instance fields -------------------------------------------------------- - - private int [] _color; - private int [] _colorCount; - private BitSet [] _allowedColors; - private int _chi; - - //~ Constructors ----------------------------------------------------------- - - /** - * @param g - */ - public BrownBacktrackColoring(final Graph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - void recursiveColor(int pos) - { - _colorCount[pos] = _colorCount[pos - 1]; - _allowedColors[pos].set(0, _colorCount[pos] + 1); - for (int i = 0; i < _neighbors[pos].length; i++) { - final int nb = _neighbors[pos][i]; - if (_color[nb] > 0) { - _allowedColors[pos].clear(_color[nb]); - } - } - for ( - int i = 1; - (i <= _colorCount[pos]) - && (_colorCount[pos] < _chi); - i++) - { - if (_allowedColors[pos].get(i)) { - _color[pos] = i; - if (pos < (_neighbors.length - 1)) { - recursiveColor(pos + 1); - } else { - _chi = _colorCount[pos]; - } - } - } - if ((_colorCount[pos] + 1) < _chi) { - _colorCount[pos]++; - _color[pos] = _colorCount[pos]; - if (pos < (_neighbors.length - 1)) { - recursiveColor(pos + 1); - } else { - _chi = _colorCount[pos]; - } - } - _color[pos] = 0; - } - - /* (non-Javadoc) - * @see org.jgrapht.experimental.alg.ExactAlgorithm#getResult() - */ - public Integer getResult(Map additionalData) - { - _chi = _neighbors.length; - _color = new int[_neighbors.length]; - _color[0] = 1; - _colorCount = new int[_neighbors.length]; - _colorCount[0] = 1; - _allowedColors = new BitSet[_neighbors.length]; - for (int i = 0; i < _neighbors.length; i++) { - _allowedColors[i] = new BitSet(1); - } - recursiveColor(1); - if (additionalData != null) { - for (int i = 0; i < _vertices.size(); i++) { - additionalData.put(_vertices.get(i), _color[i]); - } - } - return _chi; - } -} - -// End BrownBacktrackColoring.java diff --git a/src/org/jgrapht/experimental/alg/color/GreedyColoring.java b/src/org/jgrapht/experimental/alg/color/GreedyColoring.java deleted file mode 100644 index d9a586b..0000000 --- a/src/org/jgrapht/experimental/alg/color/GreedyColoring.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.jgrapht.experimental.alg.color; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.experimental.alg.*; - - -public class GreedyColoring - extends IntArrayGraphAlgorithm - implements ApproximationAlgorithm -{ - //~ Static fields/initializers --------------------------------------------- - - public static final int BEST_ORDER = 0; - public static final int NATURAL_ORDER = 1; - public static final int SMALLEST_DEGREE_LAST_ORDER = 2; - public static final int LARGEST_SATURATION_FIRST_ORDER = 3; - - //~ Instance fields -------------------------------------------------------- - - private int _order = BEST_ORDER; - - //~ Constructors ----------------------------------------------------------- - - /** - * @param g - */ - public GreedyColoring(final Graph g) - { - this(g, BEST_ORDER); - } - - /** - * @param g - */ - public GreedyColoring(final Graph g, final int method) - { - super(g); - _order = method; - } - - //~ Methods ---------------------------------------------------------------- - - int color(int [] order) - { - final int [] color = new int[_neighbors.length]; - int maxColor = 1; - BitSet usedColors = new BitSet(_neighbors.length); - - for (int i = 0; i < _neighbors.length; i++) { - final int v = (order == null) ? i : order[i]; - usedColors.clear(); - for (int j = 0; j < _neighbors[v].length; j++) { - final int nb = _neighbors[v][j]; - if (color[nb] > 0) { - usedColors.set(color[nb]); - } - } - color[v] = usedColors.nextClearBit(1); - if (color[v] > maxColor) { - maxColor = color[v]; - } - } - return maxColor; - } - - int [] smallestDegreeLastOrder() - { - final int [] order = new int[_neighbors.length]; - final int [] degree = new int[_neighbors.length]; - final List> buckets = - new ArrayList>(_neighbors.length); - int index = _neighbors.length - 1; - - for (int i = 0; i < _neighbors.length; i++) { - buckets.add(new ArrayList()); - degree[i] = _neighbors[i].length; - } - for (int i = 0; i < _neighbors.length; i++) { - buckets.get(degree[i]).add(i); - } - for (int i = 0; i < _neighbors.length; i++) { - while (buckets.get(i).size() > 0) { - final int s = buckets.get(i).size() - 1; - final int vertex = (Integer) buckets.get(i).get(s); - buckets.get(i).remove(s); - degree[vertex] = -1; - order[index--] = vertex; - for (int j = 0; j < _neighbors[vertex].length; j++) { - final int nb = _neighbors[vertex][j]; - if (degree[nb] >= 0) { - buckets.get(degree[nb]).remove(new Integer(nb)); - degree[nb]--; - buckets.get(degree[nb]).add(nb); - if (degree[nb] < i) { - i = degree[nb]; - } - } - } - } - } - return order; - } - - int [] largestSaturationFirstOrder() - { - final int [] satur = new int[_neighbors.length]; - final int [] buckets = new int[_neighbors.length]; - final int [] cumBucketSize = new int[_neighbors.length]; - final int [] bucketIndex = new int[_neighbors.length]; - int index = 0; - int maxSat = 0; - - for (int i = 0; i < _neighbors.length; i++) { - buckets[i] = i; - bucketIndex[i] = i; - } - cumBucketSize[0] = _neighbors.length; - while (index < _neighbors.length) { - while ( - (maxSat > 0) - && (cumBucketSize[maxSat] == cumBucketSize[maxSat - 1])) - { - cumBucketSize[maxSat--] = 0; - } - final int v = buckets[cumBucketSize[maxSat] - 1]; - cumBucketSize[maxSat]--; - satur[v] = -1; - index++; - for (int j = 0; j < _neighbors[v].length; j++) { - final int nb = (int) _neighbors[v][j]; - final int bi = bucketIndex[nb]; - if (satur[nb] >= 0) { - if (bi != (cumBucketSize[satur[nb]] - 1)) { - buckets[bi] = buckets[cumBucketSize[satur[nb]] - 1]; - buckets[cumBucketSize[satur[nb]] - 1] = nb; - bucketIndex[nb] = cumBucketSize[satur[nb]] - 1; - bucketIndex[buckets[bi]] = bi; - } - cumBucketSize[satur[nb]]--; - satur[nb]++; - if (cumBucketSize[satur[nb]] == 0) { - cumBucketSize[satur[nb]] = - cumBucketSize[satur[nb] - 1] + 1; - } - if (satur[nb] > maxSat) { - maxSat = satur[nb]; - } - } - } - } - Collections.reverse(Arrays.asList(buckets)); - return buckets; - } - - public Integer getLowerBound(Map optionalData) - { - return 0; - } - - public Integer getUpperBound(Map optionalData) - { - switch (_order) { - case BEST_ORDER: - return Math.min( - Math.min(color(null), color(smallestDegreeLastOrder())), - color(largestSaturationFirstOrder())); - case NATURAL_ORDER: - return color(null); - case SMALLEST_DEGREE_LAST_ORDER: - return color(smallestDegreeLastOrder()); - case LARGEST_SATURATION_FIRST_ORDER: - return color(largestSaturationFirstOrder()); - } - return _neighbors.length; - } - - public boolean isExact() - { - return false; - } -} - -// End GreedyColoring.java diff --git a/src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java b/src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java deleted file mode 100644 index 7a89dc6..0000000 --- a/src/org/jgrapht/experimental/dag/DirectedAcyclicGraph.java +++ /dev/null @@ -1,1199 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * DirectedAcyclicGraph.java - * ------------------- - * (C) Copyright 2008-2008, by Peter Giles and Contributors. - * - * Original Author: Peter Giles - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 17-Mar-2008 : Initial revision (PG); - * 23-Aug-2008 : Added VisitedBitSetImpl and made it the default (JVS); - * - */ -package org.jgrapht.experimental.dag; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - *

      DirectedAcyclicGraph implements a DAG that can be modified (vertices & - * edges added and removed), is guaranteed to remain acyclic, and provides fast - * topological order iteration.

      - * - *

      This is done using a dynamic topological sort which is based on the - * algorithm PK described in "D. Pearce & P. Kelly, 2007: A Dynamic - * Topological Sort Algorithm for Directed Acyclic Graphs", (see Paper or ACM link for details). - *

      - * - *

      The implementation differs from the algorithm specified in the above paper - * in some ways, perhaps most notably in that the topological ordering is stored - * by default using two HashMaps, which will have some effects on runtime, but - * also allows for vertex addition and removal, and other operations which are - * helpful for manipulating or combining DAGs. This storage mechanism is - * pluggable for subclassers.

      - * - *

      This class makes no claims to thread safety, and concurrent usage from - * multiple threads will produce undefined results.

      - * - * @author Peter Giles, gilesp@u.washington.edu - */ -public class DirectedAcyclicGraph - extends SimpleDirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 4522128427004938150L; - - //~ Instance fields -------------------------------------------------------- - - private TopoComparator topoComparator; - - private TopoOrderMapping topoOrderMap; - - private int maxTopoIndex = 0; - private int minTopoIndex = 0; - - // this update count is used to keep internal topological iterators honest - private long topologyUpdateCount = 0; - - /** - * Pluggable VisitedFactory implementation - */ - private VisitedFactory visitedFactory = new VisitedBitSetImpl(); - - /** - * Pluggable TopoOrderMappingFactory implementation - */ - private TopoOrderMappingFactory topoOrderFactory = new TopoVertexBiMap(); - - //~ Constructors ----------------------------------------------------------- - - public DirectedAcyclicGraph(Class arg0) - { - super(arg0); - initialize(); - } - - DirectedAcyclicGraph( - Class arg0, - VisitedFactory visitedFactory, - TopoOrderMappingFactory topoOrderFactory) - { - super(arg0); - if (visitedFactory != null) { - this.visitedFactory = visitedFactory; - } - if (topoOrderFactory != null) { - this.topoOrderFactory = topoOrderFactory; - } - initialize(); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * set the topoOrderMap based on the current factory, and create the - * comparator; - */ - private void initialize() - { - topoOrderMap = topoOrderFactory.getTopoOrderMapping(); - topoComparator = new TopoComparator(topoOrderMap); - } - - /** - * iterator will traverse the vertices in topological order, meaning that - * for a directed graph G = (V,E), if there exists a path from vertex va to - * vertex vb then va is guaranteed to come before vertex vb in the iteration - * order. - * - * @return an iterator that will traverse the graph in topological order - */ - public Iterator iterator() - { - return new TopoIterator(); - } - - /** - * adds the vertex if it wasn't already in the graph, and puts it at the top - * of the internal topological vertex ordering - */ - @Override public boolean addVertex(V v) - { - boolean added = super.addVertex(v); - - if (added) { - // add to the top - ++maxTopoIndex; - topoOrderMap.putVertex(maxTopoIndex, v); - - ++topologyUpdateCount; - } - - return added; - } - - /** - * adds the vertex if it wasn't already in the graph, and puts it either at - * the top or the bottom of the topological ordering, depending on the value - * of addToTop. This may provide useful optimizations for merging - * DirectedAcyclicGraphS that become connected. - * - * @param v - * @param addToTop - * - * @return - */ - public boolean addVertex(V v, boolean addToTop) - { - boolean added = super.addVertex(v); - - if (added) { - int insertIndex; - - // add to the top - if (addToTop) { - insertIndex = ++maxTopoIndex; - } else { - insertIndex = --minTopoIndex; - } - topoOrderMap.putVertex(insertIndex, v); - - ++topologyUpdateCount; - } - return added; - } - - /** - *

      Adds the given edge and updates the internal topological order for - * consistency IFF - * - *

        - *
      • there is not already an edge (fromVertex, toVertex) in the graph - *
      • the edge does not induce a cycle in the graph - *
      - *

      - * - * @return null if the edge is already in the graph, else the created edge - * is returned - * - * @throws IllegalArgumentException If either fromVertex or toVertex is not - * a member of the graph - * @throws CycleFoundException if the edge would induce a cycle in the graph - * - * @see Graph#addEdge(Object, Object, Object) - */ - public E addDagEdge(V fromVertex, V toVertex) - throws CycleFoundException - { - Integer lb = topoOrderMap.getTopologicalIndex(toVertex); - Integer ub = topoOrderMap.getTopologicalIndex(fromVertex); - - if ((lb == null) || (ub == null)) { - throw new IllegalArgumentException( - "vertices must be in the graph already!"); - } - - if (lb < ub) { - Set df = new HashSet(); - Set db = new HashSet(); - - // Discovery - Region affectedRegion = new Region(lb, ub); - Visited visited = visitedFactory.getInstance(affectedRegion); - - // throws CycleFoundException if there is a cycle - dfsF(toVertex, df, visited, affectedRegion); - - dfsB(fromVertex, db, visited, affectedRegion); - reorder(df, db, visited); - ++topologyUpdateCount; // if we do a reorder, than the topology has - // been updated - } - - return super.addEdge(fromVertex, toVertex); - } - - /** - * identical to {@link #addDagEdge(Object, Object)}, except an unchecked - * {@link IllegalArgumentException} is thrown if a cycle would have been - * induced by this edge - */ - @Override public E addEdge(V sourceVertex, V targetVertex) - { - E result = null; - try { - result = addDagEdge(sourceVertex, targetVertex); - } catch (CycleFoundException e) { - throw new IllegalArgumentException(e); - } - return result; - } - - /** - *

      Adds the given edge and updates the internal topological order for - * consistency IFF - * - *

        - *
      • the given edge is not already a member of the graph - *
      • there is not already an edge (fromVertex, toVertex) in the graph - *
      • the edge does not induce a cycle in the graph - *
      - *

      - * - * @return true if the edge was added to the graph - * - * @throws CycleFoundException if adding an edge (fromVertex, toVertex) to - * the graph would induce a cycle. - * - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addDagEdge(V fromVertex, V toVertex, E e) - throws CycleFoundException - { - if (e == null) { - throw new NullPointerException(); - } else if (containsEdge(e)) { - return false; - } - - Integer lb = topoOrderMap.getTopologicalIndex(toVertex); - Integer ub = topoOrderMap.getTopologicalIndex(fromVertex); - - if ((lb == null) || (ub == null)) { - throw new IllegalArgumentException( - "vertices must be in the graph already!"); - } - - if (lb < ub) { - Set df = new HashSet(); - Set db = new HashSet(); - - // Discovery - Region affectedRegion = new Region(lb, ub); - Visited visited = visitedFactory.getInstance(affectedRegion); - - // throws CycleFoundException if there is a cycle - dfsF(toVertex, df, visited, affectedRegion); - - dfsB(fromVertex, db, visited, affectedRegion); - reorder(df, db, visited); - ++topologyUpdateCount; // if we do a reorder, than the topology has - // been updated - } - - return super.addEdge(fromVertex, toVertex, e); - } - - /** - * identical to {@link #addDagEdge(Object, Object, Object)}, except an - * unchecked {@link IllegalArgumentException} is thrown if a cycle would - * have been induced by this edge - */ - @Override public boolean addEdge(V sourceVertex, V targetVertex, E edge) - { - boolean result; - try { - result = addDagEdge(sourceVertex, targetVertex, edge); - } catch (CycleFoundException e) { - throw new IllegalArgumentException(e); - } - return result; - } - - // note that this can leave holes in the topological ordering, which - // (depending on the TopoOrderMap implementation) can degrade performance - // for certain operations over time - @Override public boolean removeVertex(V v) - { - boolean removed = super.removeVertex(v); - - if (removed) { - Integer topoIndex = topoOrderMap.removeVertex(v); - - // contract minTopoIndex as we are able - if (topoIndex == minTopoIndex) { - while ( - (minTopoIndex < 0) - && (null == topoOrderMap.getVertex(minTopoIndex))) - { - ++minTopoIndex; - } - } - - // contract maxTopoIndex as we are able - if (topoIndex == maxTopoIndex) { - while ( - (maxTopoIndex > 0) - && (null == topoOrderMap.getVertex(maxTopoIndex))) - { - --maxTopoIndex; - } - } - - ++topologyUpdateCount; - } - - return removed; - } - - @Override public boolean removeAllVertices(Collection arg0) - { - boolean removed = super.removeAllVertices(arg0); - - topoOrderMap.removeAllVertices(); - - maxTopoIndex = 0; - minTopoIndex = 0; - - ++topologyUpdateCount; - - return removed; - } - - /** - * Depth first search forward, building up the set (df) of forward-connected - * vertices in the Affected Region - * - * @param vertex the vertex being visited - * @param df the set we are populating with forward connected vertices in - * the Affected Region - * @param visited a simple data structure that lets us know if we already - * visited a node with a given topo index - * @param topoIndexMap for quick lookups, a map from vertex to topo index in - * the AR - * @param ub the topo index of the original fromVertex -- used for cycle - * detection - * - * @throws CycleFoundException if a cycle is discovered - */ - private void dfsF( - V vertex, - Set df, - Visited visited, - Region affectedRegion) - throws CycleFoundException - { - int topoIndex = topoOrderMap.getTopologicalIndex(vertex); - - // Assumption: vertex is in the AR and so it will be in visited - visited.setVisited(topoIndex); - - df.add(vertex); - - for (E outEdge : outgoingEdgesOf(vertex)) { - V nextVertex = getEdgeTarget(outEdge); - Integer nextVertexTopoIndex = - topoOrderMap.getTopologicalIndex(nextVertex); - - if (nextVertexTopoIndex.intValue() == affectedRegion.finish) { - // reset visited - try { - for (V visitedVertex : df) { - visited.clearVisited( - topoOrderMap.getTopologicalIndex(visitedVertex)); - } - } catch (UnsupportedOperationException e) { - // okay, fine, some implementations (ones that automatically - // clear themselves out) don't work this way - } - throw new CycleFoundException(); - } - - // note, order of checks is important as we need to make sure the - // vertex is in the affected region before we check its visited - // status (otherwise we will be causing an - // ArrayIndexOutOfBoundsException). - if (affectedRegion.isIn(nextVertexTopoIndex) - && !visited.getVisited(nextVertexTopoIndex)) - { - dfsF(nextVertex, df, visited, affectedRegion); // recurse - } - } - } - - /** - * Depth first search backward, building up the set (db) of back-connected - * vertices in the Affected Region - * - * @param vertex the vertex being visited - * @param db the set we are populating with back-connected vertices in the - * AR - * @param visited - * @param topoIndexMap - */ - private void dfsB( - V vertex, - Set db, - Visited visited, - Region affectedRegion) - { - // Assumption: vertex is in the AR and so we will get a topoIndex from - // the map - int topoIndex = topoOrderMap.getTopologicalIndex(vertex); - visited.setVisited(topoIndex); - - db.add(vertex); - - for (E inEdge : incomingEdgesOf(vertex)) { - V previousVertex = getEdgeSource(inEdge); - Integer previousVertexTopoIndex = - topoOrderMap.getTopologicalIndex(previousVertex); - - // note, order of checks is important as we need to make sure the - // vertex is in the affected region before we check its visited - // status (otherwise we will be causing an - // ArrayIndexOutOfBoundsException). - if (affectedRegion.isIn(previousVertexTopoIndex) - && !visited.getVisited(previousVertexTopoIndex)) - { - // if prevousVertexTopoIndex != null, the vertex is in the - // Affected Region according to our topoIndexMap - - dfsB(previousVertex, db, visited, affectedRegion); - } - } - } - - @SuppressWarnings("unchecked") - private void reorder(Set df, Set db, Visited visited) - { - List topoDf = new ArrayList(df); - List topoDb = new ArrayList(db); - - Collections.sort(topoDf, topoComparator); - Collections.sort(topoDb, topoComparator); - - // merge these suckers together in topo order - - SortedSet availableTopoIndices = new TreeSet(); - - // we have to cast to the generic type, can't do "new V[size]" in java - // 5; - V [] bigL = (V []) new Object[df.size() + db.size()]; - int lIndex = 0; // this index is used for the sole purpose of pushing - // into - - // the correct index of bigL - - // assume (for now) that we are resetting visited - boolean clearVisited = true; - - for (V vertex : topoDb) { - Integer topoIndex = topoOrderMap.getTopologicalIndex(vertex); - - // add the available indices to the set - availableTopoIndices.add(topoIndex); - - bigL[lIndex++] = vertex; - - if (clearVisited) { // reset visited status if supported - try { - visited.clearVisited(topoIndex); - } catch (UnsupportedOperationException e) { - clearVisited = false; - } - } - } - - for (V vertex : topoDf) { - Integer topoIndex = topoOrderMap.getTopologicalIndex(vertex); - - // add the available indices to the set - availableTopoIndices.add(topoIndex); - bigL[lIndex++] = vertex; - - if (clearVisited) { // reset visited status if supported - try { - visited.clearVisited(topoIndex); - } catch (UnsupportedOperationException e) { - clearVisited = false; - } - } - } - - lIndex = 0; // reusing lIndex - for (Integer topoIndex : availableTopoIndices) { - // assign the indexes to the elements of bigL in order - V vertex = bigL[lIndex++]; // note the post-increment - topoOrderMap.putVertex(topoIndex, vertex); - } - } - - //~ Inner Interfaces ------------------------------------------------------- - - /** - * For performance tuning, an interface for storing the topological ordering - * - * @author gilesp - */ - public interface TopoOrderMapping - extends Serializable - { - /** - * add a vertex at the given topological index. - * - * @param index - * @param vertex - */ - public void putVertex(Integer index, V vertex); - - /** - * get the vertex at the given topological index. - * - * @param index - * - * @return - */ - public V getVertex(Integer index); - - /** - * get the topological index of the given vertex. - * - * @param vertex - * - * @return the index that the vertex is at, or null if the vertex isn't - * in the topological ordering - */ - public Integer getTopologicalIndex(V vertex); - - /** - * remove the given vertex from the topological ordering - * - * @param vertex - * - * @return the index that the vertex was at, or null if the vertex - * wasn't in the topological ordering - */ - public Integer removeVertex(V vertex); - - /** - * remove all vertices from the topological ordering - */ - public void removeAllVertices(); - } - - public interface TopoOrderMappingFactory - { - public TopoOrderMapping getTopoOrderMapping(); - } - - /** - * this interface allows specification of a strategy for marking vertices as - * visited (based on their topological index, so the vertex type isn't part - * of the interface). - */ - public interface Visited - { - /** - * mark the given topological index as visited - * - * @param index the topological index - */ - public void setVisited(int index); - - /** - * has the given topological index been visited? - * - * @param index the topological index - */ - public boolean getVisited(int index); - - /** - * Clear the visited state of the given topological index - * - * @param index - * - * @throws UnsupportedOperationException if the implementation doesn't - * support (or doesn't need) clearance. For example, if the factory - * vends a new instance every time, it is a waste of cycles to clear the - * state after the search of the Affected Region is done, so an - * UnsupportedOperationException *should* be thrown. - */ - public void clearVisited(int index) - throws UnsupportedOperationException; - } - - /** - * interface for a factory that vends Visited implementations - * - * @author gilesp - */ - public interface VisitedFactory - extends Serializable - { - public Visited getInstance(Region affectedRegion); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Note, this is a lazy and incomplete implementation, with assumptions that - * inputs are in the given topoIndexMap - * - * @param - * - * @author gilesp - */ - private static class TopoComparator - implements Comparator, - Serializable - { - /** - */ - private static final long serialVersionUID = 1L; - - private TopoOrderMapping topoOrderMap; - - public TopoComparator(TopoOrderMapping topoOrderMap) - { - this.topoOrderMap = topoOrderMap; - } - - public int compare(V o1, V o2) - { - return topoOrderMap.getTopologicalIndex(o1).compareTo( - topoOrderMap.getTopologicalIndex(o2)); - } - } - - /** - * a dual HashMap implementation - * - * @author gilesp - */ - private class TopoVertexBiMap - implements TopoOrderMapping, - TopoOrderMappingFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final Map topoToVertex = new HashMap(); - private final Map vertexToTopo = new HashMap(); - - public void putVertex(Integer index, V vertex) - { - topoToVertex.put(index, vertex); - vertexToTopo.put(vertex, index); - } - - public V getVertex(Integer index) - { - return topoToVertex.get(index); - } - - public Integer getTopologicalIndex(V vertex) - { - Integer topoIndex = vertexToTopo.get(vertex); - return topoIndex; - } - - public Integer removeVertex(V vertex) - { - Integer topoIndex = vertexToTopo.remove(vertex); - if (topoIndex != null) { - topoToVertex.remove(topoIndex); - } - return topoIndex; - } - - public void removeAllVertices() - { - vertexToTopo.clear(); - topoToVertex.clear(); - } - - public TopoOrderMapping getTopoOrderMapping() - { - return this; - } - } - - /** - * For performance and flexibility uses an ArrayList for topological index - * to vertex mapping, and a HashMap for vertex to topological index mapping. - * - * @author gilesp - */ - public class TopoVertexMap - implements TopoOrderMapping, - TopoOrderMappingFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final List topoToVertex = new ArrayList(); - private final Map vertexToTopo = new HashMap(); - - public void putVertex(Integer index, V vertex) - { - int translatedIndex = translateIndex(index); - - // grow topoToVertex as needed to accommodate elements - while ((translatedIndex + 1) > topoToVertex.size()) { - topoToVertex.add(null); - } - - topoToVertex.set(translatedIndex, vertex); - vertexToTopo.put(vertex, index); - } - - public V getVertex(Integer index) - { - return topoToVertex.get(translateIndex(index)); - } - - public Integer getTopologicalIndex(V vertex) - { - return vertexToTopo.get(vertex); - } - - public Integer removeVertex(V vertex) - { - Integer topoIndex = vertexToTopo.remove(vertex); - if (topoIndex != null) { - topoToVertex.set(translateIndex(topoIndex), null); - } - return topoIndex; - } - - public void removeAllVertices() - { - vertexToTopo.clear(); - topoToVertex.clear(); - } - - public TopoOrderMapping getTopoOrderMapping() - { - return this; - } - - /** - * We translate the topological index to an ArrayList index. We have to - * do this because topological indices can be negative, and we want to - * do it because we can make better use of space by only needing an - * ArrayList of size |AR|. - * - * @param unscaledIndex - * - * @return the ArrayList index - */ - private final int translateIndex(int index) - { - if (index >= 0) { - return 2 * index; - } - return -1 * ((index * 2) - 1); - } - } - - /** - * Region is an *inclusive* range of indices. Esthetically displeasing, but - * convenient for our purposes. - * - * @author gilesp - */ - public static class Region - implements Serializable - { - /** - */ - private static final long serialVersionUID = 1L; - - public final int start; - public final int finish; - - public Region(int start, int finish) - { - if (start > finish) { - throw new IllegalArgumentException( - "(start > finish): invariant broken"); - } - this.start = start; - this.finish = finish; - } - - public int getSize() - { - return (finish - start) + 1; - } - - public boolean isIn(int index) - { - return (index >= start) && (index <= finish); - } - } - - /** - * This implementation is close to the performance of VisitedArrayListImpl, - * with 1/8 the memory usage. - * - * @author perfecthash - */ - public static class VisitedBitSetImpl - implements Visited, - VisitedFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final BitSet visited = new BitSet(); - - private Region affectedRegion; - - public Visited getInstance(Region affectedRegion) - { - this.affectedRegion = affectedRegion; - - return this; - } - - public void setVisited(int index) - { - visited.set(translateIndex(index), true); - } - - public boolean getVisited(int index) - { - return visited.get(translateIndex(index)); - } - - public void clearVisited(int index) - throws UnsupportedOperationException - { - visited.clear(translateIndex(index)); - } - - /** - * We translate the topological index to an ArrayList index. We have to - * do this because topological indices can be negative, and we want to - * do it because we can make better use of space by only needing an - * ArrayList of size |AR|. - * - * @param unscaledIndex - * - * @return the ArrayList index - */ - private int translateIndex(int index) - { - return index - affectedRegion.start; - } - } - - /** - * This implementation seems to offer the best performance in most cases. It - * grows the internal ArrayList as needed to be as large as |AR|, so it will - * be more memory intensive than the HashSet implementation, and unlike the - * Array implementation, it will hold on to that memory (it expands, but - * never contracts). - * - * @author gilesp - */ - public static class VisitedArrayListImpl - implements Visited, - VisitedFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final List visited = new ArrayList(); - - private Region affectedRegion; - - public Visited getInstance(Region affectedRegion) - { - // Make sure visited is big enough - int minSize = (affectedRegion.finish - affectedRegion.start) + 1; - /* plus one because the region range is inclusive of both indices */ - - while (visited.size() < minSize) { - visited.add(Boolean.FALSE); - } - - this.affectedRegion = affectedRegion; - - return this; - } - - public void setVisited(int index) - { - visited.set(translateIndex(index), Boolean.TRUE); - } - - public boolean getVisited(int index) - { - Boolean result = null; - - result = visited.get(translateIndex(index)); - - return result; - } - - public void clearVisited(int index) - throws UnsupportedOperationException - { - visited.set(translateIndex(index), Boolean.FALSE); - } - - /** - * We translate the topological index to an ArrayList index. We have to - * do this because topological indices can be negative, and we want to - * do it because we can make better use of space by only needing an - * ArrayList of size |AR|. - * - * @param unscaledIndex - * - * @return the ArrayList index - */ - private int translateIndex(int index) - { - return index - affectedRegion.start; - } - } - - /** - * This implementation doesn't seem to perform as well, though I can imagine - * circumstances where it should shine (lots and lots of vertices). It also - * should have the lowest memory footprint as it only uses storage for - * indices that have been visited. - * - * @author gilesp - */ - public static class VisitedHashSetImpl - implements Visited, - VisitedFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final Set visited = new HashSet(); - - public Visited getInstance(Region affectedRegion) - { - visited.clear(); - return this; - } - - public void setVisited(int index) - { - visited.add(index); - } - - public boolean getVisited(int index) - { - return visited.contains(index); - } - - public void clearVisited(int index) - throws UnsupportedOperationException - { - throw new UnsupportedOperationException(); - } - } - - /** - * This implementation, somewhat to my surprise, is slower than the - * ArrayList version, probably due to its reallocation of the underlying - * array for every topology reorder that is required. - * - * @author gilesp - */ - public static class VisitedArrayImpl - implements Visited, - VisitedFactory - { - /** - */ - private static final long serialVersionUID = 1L; - - private final boolean [] visited; - - private final Region region; - - /** - * Constructs empty factory instance - */ - public VisitedArrayImpl() - { - this(null); - } - - public VisitedArrayImpl(Region region) - { - if (region == null) { // make empty instance - this.visited = null; - this.region = null; - } else { // fill in the needed pieces - this.region = region; - - // initialized to all false by default - visited = new boolean[region.getSize()]; - } - } - - public Visited getInstance(Region affectedRegion) - { - return new VisitedArrayImpl(affectedRegion); - } - - public void setVisited(int index) - { - try { - visited[index - region.start] = true; - } catch (ArrayIndexOutOfBoundsException e) { - /* - log.error("Visited set operation out of region boundaries", e); - */ - throw e; - } - } - - public boolean getVisited(int index) - { - try { - return visited[index - region.start]; - } catch (ArrayIndexOutOfBoundsException e) { - /* - log.error("Visited set operation out of region boundaries", e); - */ - throw e; - } - } - - public void clearVisited(int index) - throws UnsupportedOperationException - { - throw new UnsupportedOperationException(); - } - } - - /** - * Exception used in dfsF when a cycle is found - * - * @author gilesp - */ - public static class CycleFoundException - extends Exception - { - private static final long serialVersionUID = 5583471522212552754L; - } - - /** - * iterator which follows topological order - * - * @author gilesp - */ - private class TopoIterator - implements Iterator - { - private int currentTopoIndex; - private final long updateCountAtCreation; - private Integer nextIndex = null; - - public TopoIterator() - { - updateCountAtCreation = topologyUpdateCount; - currentTopoIndex = minTopoIndex - 1; - } - - public boolean hasNext() - { - if (updateCountAtCreation != topologyUpdateCount) { - throw new ConcurrentModificationException(); - } - - nextIndex = getNextIndex(); - return nextIndex != null; - } - - public V next() - { - if (updateCountAtCreation != topologyUpdateCount) { - throw new ConcurrentModificationException(); - } - - if (nextIndex == null) { - // find nextIndex - nextIndex = getNextIndex(); - } - if (nextIndex == null) { - throw new NoSuchElementException(); - } - currentTopoIndex = nextIndex; - nextIndex = null; - return topoOrderMap.getVertex(currentTopoIndex); //topoToVertex.get(currentTopoIndex); - } - - public void remove() - { - if (updateCountAtCreation != topologyUpdateCount) { - throw new ConcurrentModificationException(); - } - - V vertexToRemove = null; - if (null - != (vertexToRemove = - topoOrderMap.getVertex( - currentTopoIndex))) - { - topoOrderMap.removeVertex(vertexToRemove); - } else { - // should only happen if next() hasn't been called - throw new IllegalStateException(); - } - } - - private Integer getNextIndex() - { - for (int i = currentTopoIndex + 1; i <= maxTopoIndex; i++) { - if (null != topoOrderMap.getVertex(i)) { - return i; - } - } - return null; - } - } -} - -// End DirectedAcyclicGraph.java diff --git a/src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java deleted file mode 100644 index 433d1a1..0000000 --- a/src/org/jgrapht/experimental/equivalence/EquivalenceComparator.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceComparator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -/** - * This interface distinguishes between Equivalence sets. - * - *

      It is similar, in concept, to the Object.hashcode() and Object.equals() - * methods, but instead of checking whether two objects are equal, it is used to - * check whether they are part of the same Equivalence group, where the - * definition of an "equivalence" is defined by the implementation of this - * interface. - * - *

      A specific usage of it is shown below, but it may be used outside of the - * graph-theory class library. - * - *

      In Isomorphism, edges/vertexes matching may relay on none/some/all of the - * vertex/edge properties. For example, if a vertex representing a person - * contains two properties: gender(male/female) and person name(string), we can - * decide that to check isomorphism in vertex groups of gender only. Meaning if - * this is the graph: - * - *

      (male,"Don")---->(female,"Dana")--->(male,"John") - * - *

      if there is no equivalence set at all , this graph can be described as: - * (1)---->(2)---->(3) - * - *

      if the equivalence set is determined only by the gender property : - * (male)---->(female)---->(male) - * - *

      and if it is determined by both properties: (the original figure) The - * isomorphism inspection may return different result according to this choice. - * If the other graph is: (male,"Don")--->(male,"Sunny")---->(male,"Jo") In no - * eq.set they are Isomorphic, but for the two other cases they are not. Other - * examples: Nodes with the same degree, Edges with the same weight, Graphs with - * the same number of nodes and edges. - * - * @param the type of the elements in the set - * @param the type of the context the element is compared against, e.g. a - * Graph - * - * @author Assaf - * @since Jul 15, 2005 - */ -public interface EquivalenceComparator -{ - //~ Methods ---------------------------------------------------------------- - - public boolean equivalenceCompare( - E arg1, - E arg2, - C context1, - C context2); - - public int equivalenceHashcode(E arg1, C context); -} - -// End EquivalenceComparator.java diff --git a/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java deleted file mode 100644 index 4f7871b..0000000 --- a/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChain.java +++ /dev/null @@ -1,71 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceComparatorChain.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -/** - * A container of comparators, which are tested in a chain until the first - * result can be supplied. It implements the EquivalenceComparator, so chains - * can include other chains. The first check will use the current comparator and - * not the next one. So, make sure to use the one which has better performance - * first. (This class follows the "Composite" design-pattern). - * - * @param the type of the elements in the set - * @param the type of the context the element is compared against, e.g. a - * Graph - * - * @author Assaf - * @since Jul 22, 2005 - */ -public interface EquivalenceComparatorChain - extends EquivalenceComparator -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Adds a comparator which will also test equivalence. For - * equivalenceCompare(), the return value is a logical AND of the two - * comparators. The first check will use the first comparator before the - * next one. Make sure to put the one which has better performance first. - * For equivalenceHashcode(), the resulting hashes will be rehashed - * together. This method may be used multiple times to create a long "chain" - * of comparators. - */ - public void appendComparator(EquivalenceComparator comparatorAfter); -} - -// End EquivalenceComparatorChain.java diff --git a/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java b/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java deleted file mode 100644 index b6f9fd3..0000000 --- a/src/org/jgrapht/experimental/equivalence/EquivalenceComparatorChainBase.java +++ /dev/null @@ -1,167 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceComparatorChainBase.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: EquivalenceComparatorChainBase.java 485 2006-06-26 09:12:14Z perfecthash - * $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -import java.util.*; - - -/** - * This class implements comparator chaining. - * - *

      Usage examples: - *

    1. graph-theory, node equivalence: You can create a comparator for - * the inDegree of a node, another for the total weight of outDegree edges, and - * a third which checks the business content of the node. You know that the - * first topological comparators has dozens of different groups, but the - * buisness comparator has only two, and they are hard to check . The best - * performance will be gained by: - * - *
      - *

      EquivalenceComparatorChainBase eqChain = new - * EquivalenceComparatorChainBase(fastNodesDegreeComparator); - * - *

      eqChain.addComparatorAfter(ABitSlowerEdgeWeightComparator); - * - *

      eqChain.addComparatorAfter(slowestBuisnessContentsComparator); - *

      - * - * @param the type of the elements in the set - * @param the type of the context the element is compared against, e.g. a - * Graph - * - * @author Assaf - * @since Jul 22, 2005 - */ -public class EquivalenceComparatorChainBase - implements EquivalenceComparatorChain -{ - //~ Instance fields -------------------------------------------------------- - - private List> chain; - - //~ Constructors ----------------------------------------------------------- - - /** - */ - public EquivalenceComparatorChainBase( - EquivalenceComparator firstComaparator) - { - this.chain = - new LinkedList>(); - this.chain.add(firstComaparator); - } - - //~ Methods ---------------------------------------------------------------- - - /* (non-Javadoc) - * @see - * - * - * - * - * - * org.jgrapht.experimental.equivalence.EquivalenceComparatorChain#addComparatorAfter(org.jgrapht.experimental.equivalence.EquivalenceComparator) - */ - @SuppressWarnings("unchecked") - public void appendComparator(EquivalenceComparator comparatorAfter) - { - if (comparatorAfter != null) { - this.chain.add(comparatorAfter); - } - } - - /** - * Implements logical AND between the comparators results. Iterates through - * the comparators chain until one of them returns false. If none returns - * false, this method returns true. - * - * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, - * Object) - */ - public boolean equivalenceCompare( - E arg1, - E arg2, - C context1, - C context2) - { - for ( - EquivalenceComparator currentComparator - : this.chain) - { - if (!currentComparator.equivalenceCompare( - arg1, - arg2, - context1, - context2)) - { - return false; - } - } - return true; - } - - /** - * Rehashes the concatenation of the results of all single hashcodes. - * - * @see EquivalenceComparator#equivalenceHashcode(Object, Object) - */ - public int equivalenceHashcode(E arg1, C context) - { - StringBuffer hashStringBuffer = new StringBuffer(); - for ( - ListIterator> iter = - this.chain.listIterator(); - iter.hasNext();) - { - EquivalenceComparator currentComparator = - iter.next(); - int currentHashCode = - currentComparator.equivalenceHashcode(arg1, context); - hashStringBuffer.append(currentHashCode); - - // add a delimeter only if needed for next - if (iter.hasNext()) { - hashStringBuffer.append('+'); - } - } - return hashStringBuffer.toString().hashCode(); - } -} - -// End EquivalenceComparatorChainBase.java diff --git a/src/org/jgrapht/experimental/equivalence/EquivalenceSet.java b/src/org/jgrapht/experimental/equivalence/EquivalenceSet.java deleted file mode 100644 index 43b976a..0000000 --- a/src/org/jgrapht/experimental/equivalence/EquivalenceSet.java +++ /dev/null @@ -1,206 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceSet.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -import java.util.*; - - -/** - * EquivalenceSet is a Set of elements which have been determined to be - * equivalent using EquivalenceComparator. The class makes sure the set size - * will be one or more. - *
    2. The group can only be created using the factory method - * createGroupWithElement(). - *
    3. The equals and hashcode of a group uses the EquivalenceComparator on one - * of the group members, thus it is actually checking whether the "other" is in - * the same group. - * - * @param the type of the elements in the set - * @param the type of the context the element is compared against, e.g. a - * Graph - * - * @author Assaf - * @since Jul 21, 2005 - */ -public class EquivalenceSet -{ - //~ Instance fields -------------------------------------------------------- - - /** - * The comparator used to define the group - */ - protected EquivalenceComparator eqComparator; - protected C comparatorContext; - - /** - * Contains the current elements of the group - */ - protected Set elementsSet; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructs a new EquivalenceSet, filled with the aElement parameter and a - * reference to the comparator which is used. - */ - public EquivalenceSet( - E aElement, - EquivalenceComparator aEqComparator, - C aComparatorContext) - { - this.eqComparator = aEqComparator; - this.comparatorContext = aComparatorContext; - - this.elementsSet = new HashSet(); - this.elementsSet.add(aElement); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns an arbitrary object from the group. There is no guarantee as to - * which will be returned, and whether the same will be returned on the next - * call. - */ - public E getRepresentative() - { - return elementsSet.iterator().next(); - } - - public C getContext() - { - return this.comparatorContext; - } - - public int size() - { - return elementsSet.size(); - } - - /** - * Adds an element to the group. It does not check it for equivalance . You - * must make sure it does, using equals(). - */ - public void add(E element) - { - this.elementsSet.add(element); - } - - public boolean equivalentTo(E aOther, C aOtherContext) - { - boolean result = - this.eqComparator.equivalenceCompare( - this.getRepresentative(), - aOther, - this.comparatorContext, - aOtherContext); - return result; - } - - /** - * Uses the equivalenceCompare() of the comparator to compare a - * representation of this group, taken using this.getRepresentative(), and a - * representation of the other object, which may be the object itself, or, - * if it is an equivalence group too, other.getRepresentative() - */ - // FIXME REVIEW hb 26-Jan-2006: I think throwing the exception is kind of - // odd, - // - it feels like violating the contract of Object.equals() - // From what I understand, comparing any object to any other object should - // be - // possible at all times and simply return false if they are not equal. - // Uncomparable objects beeing unequal. - // Suggestion: remove the exception, at best, test on this specific class - // and - // write a warning or some such. - - @SuppressWarnings("unchecked") - public boolean equals(Object other) - { - E otherRepresentative = null; - C otherContext = null; - if (other instanceof EquivalenceSet) { - otherRepresentative = - ((EquivalenceSet) other).getRepresentative(); - otherContext = ((EquivalenceSet) other).getContext(); - } else { - throw new ClassCastException( - "can check equal() only of EqualityGroup"); - } - - boolean result = - this.eqComparator.equivalenceCompare( - this.getRepresentative(), - otherRepresentative, - this.comparatorContext, - otherContext); - return result; - } - - /** - * Uses a representative to calculate the group hashcode using - * equivalenceHashcode(). - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() - { - int result = - this.eqComparator.equivalenceHashcode( - this.getRepresentative(), - this.comparatorContext); - return result; - } - - public String toString() - { - return "Eq.Group=" + this.elementsSet.toString(); - } - - /** - * Returns the elements of the group. The order of the elements in the - * returned array is not guaranteed. In other words, two calls to the same - * object may return different order. - */ - public Object [] toArray() - { - return this.elementsSet.toArray(); - } -} - -// End EquivalenceSet.java diff --git a/src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java b/src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java deleted file mode 100644 index 0b3aeee..0000000 --- a/src/org/jgrapht/experimental/equivalence/EquivalenceSetCreator.java +++ /dev/null @@ -1,262 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceSetCreator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -import java.util.*; - - -/** - * FIXME Document me. - * - * @param the type of the elements in the set - * @param the type of the context the element is compared against, e.g. a - * Graph TODO hb 060208: REVIEW: Using an array for aElementsArray causes - * problems with generics elsewhere - changed to List? - * - * @author Assaf - * @since Jul 21, 2005 - */ -public class EquivalenceSetCreator -{ - //~ Static fields/initializers --------------------------------------------- - - private static final EqGroupSizeComparator groupSizeComparator = - new EqGroupSizeComparator(); - - //~ Methods ---------------------------------------------------------------- - - /** - * Checks for equivalance groups in the aElementsArray. Returns an ordered - * array of them, where the smallest one is the first in the array. - * - * @param aElementsArray - * @param aEqComparator - * - * @deprecated To improve type-safety when using generics, use {@link - * #createEqualityGroupOrderedArray(Collection, EquivalenceComparator, - * Object)} - */ - @Deprecated public static EquivalenceSet [] - createEqualityGroupOrderedArray( - EE [] aElementsArray, - EquivalenceComparator aEqComparator, - CC aContext) - { - return (createEqualityGroupOrderedArray( - Arrays.asList(aElementsArray), - aEqComparator, - aContext)); - // ArrayList> arrayList = new - // ArrayList>(); - // - // HashMap>> map - // = createEqualityGroupMap(aElementsArray, aEqComparator, - // aContext); // each of the map values is a list with one or - // more groups in it. // Object[] array = map.values().toArray(); - // // for (int i = 0; i < array.length; i++) // { // List list = - // (List)array[i]; - // - // for (List> list : - // map.values() ) { for (EquivalenceSet - // eSet : list ) { arrayList.add( eSet ); } } - // - // - // now we got all the eq. groups in an array list. we need to sort - // // them EquivalenceSet [] resultArray = new EquivalenceSet - // [arrayList.size()]; arrayList.toArray(resultArray); - // Arrays.sort(resultArray, groupSizeComparator); return - // resultArray; - } - - /** - * Checks for equivalance groups in the aElementsArray. Returns an ordered - * array of them, where the smallest one is the first in the array. - * - * @param elements - * @param aEqComparator TODO hb 060208: Using an array for aElementsArray - * causes problems with generics elsewhere - change to List? - */ - public static EquivalenceSet [] createEqualityGroupOrderedArray( - Collection elements, - EquivalenceComparator aEqComparator, - CC aContext) - { - ArrayList> arrayList = - new ArrayList>(); - - HashMap>> map = - createEqualityGroupMap(elements, aEqComparator, aContext); - // each of the map values is a list with one or more groups in it. - // Object[] array = map.values().toArray(); - // for (int i = 0; i < array.length; i++) - // { - // List list = (List)array[i]; - - for (List> list : map.values()) { - for (EquivalenceSet eSet : list) { - arrayList.add(eSet); - } - } - - // now we got all the eq. groups in an array list. we need to sort - // them - EquivalenceSet [] resultArray = new EquivalenceSet[arrayList.size()]; - arrayList.toArray(resultArray); - Arrays.sort(resultArray, groupSizeComparator); - return resultArray; - } - - /** - * The data structure we use to store groups is a map, where the key is - * eqGroupHashCode, and the value is list, containing one or more eqGroup - * which match this hash. - * - * @param elements - * @param aEqComparator - * - * @return a hashmap with key=group hashcode , value = list of eq.groups - * which match that hash. TODO hb 060208: Using an array for aElementsArray - * causes problems with generics elsewhere - change to List? - */ - private static HashMap>> createEqualityGroupMap( - Collection elements, - EquivalenceComparator aEqComparator, - CC aComparatorContext) - { - HashMap>> equalityGroupMap = - new HashMap>>( - elements.size()); - - for (EE curentElement : elements) { - int hashcode = - aEqComparator.equivalenceHashcode( - curentElement, - aComparatorContext); - List> list = - equalityGroupMap.get(Integer.valueOf(hashcode)); - - // determine the type of value. It can be null(no value yet) , - // or a list of EquivalenceSet - - if (list == null) { - // create list with one element in it - list = new LinkedList>(); - list.add( - new EquivalenceSet( - curentElement, - aEqComparator, - aComparatorContext)); - - // This is the first one .add it to the map , in an eqGroup - equalityGroupMap.put(Integer.valueOf(hashcode), list); - } else { - boolean eqWasFound = false; - - // we need to check the groups in the list. If none are good, - // create a new one - for (EquivalenceSet eqGroup : list) { - if (eqGroup.equivalentTo( - curentElement, - aComparatorContext)) - { - // add it to the list and break - eqGroup.add(curentElement); - eqWasFound = true; - break; - } - } - - // if no match was found add it to the list as a new group - if (!eqWasFound) { - list.add( - new EquivalenceSet( - curentElement, - aEqComparator, - aComparatorContext)); - } - } - } - - return equalityGroupMap; - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Functor used to order groups by size (number of elements in the group) - * from the smallest to the biggest. If they have the same size, uses the - * hashcode of the group to compare from the smallest to the biggest. Note - * that it is inconsistent with equals(). See Object.equals() javadoc. - * - * @author Assaf - * @since Jul 22, 2005 - */ - private static class EqGroupSizeComparator - implements Comparator - { - /** - * compare by size , then (if size equal) by hashcode - * - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - */ - @SuppressWarnings("unchecked") - public int compare(EquivalenceSet arg1, EquivalenceSet arg2) - { - int eqGroupSize1 = arg1.size(); - int eqGroupSize2 = arg2.size(); - if (eqGroupSize1 > eqGroupSize2) { - return 1; - } else if (eqGroupSize1 < eqGroupSize2) { - return -1; - } else { // size equal , compare hashcodes - int eqGroupHash1 = arg1.hashCode(); - int eqGroupHash2 = arg2.hashCode(); - if (eqGroupHash1 > eqGroupHash2) { - return 1; - } else if (eqGroupHash1 < eqGroupHash2) { - return -1; - } else { - return 0; - } - } - } - } -} - -// End EquivalenceSetCreator.java diff --git a/src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java b/src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java deleted file mode 100644 index 43c9afa..0000000 --- a/src/org/jgrapht/experimental/equivalence/UniformEquivalenceComparator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * UniformEquivalenceComparator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.equivalence; - -/** - * This Equivalence comparator acts as if all elements are in one big global - * equivalence class. Useful when a comparator is needed, but there is no - * important difference between the elements. equivalenceCompare() always return - * true; equivalenceHashcode() always returns 0. - * - * @author Assaf - * @since Jul 21, 2005 - */ -public class UniformEquivalenceComparator - implements EquivalenceComparator -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Always returns true. - * - * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, - * Object) - */ - public boolean equivalenceCompare( - E arg1, - E arg2, - C context1, - C context2) - { - return true; - } - - /** - * Always returns 0. - * - * @see EquivalenceComparator#equivalenceHashcode(Object, Object) - */ - public int equivalenceHashcode(E arg1, C context) - { - return 0; - } -} - -// End UniformEquivalenceComparator.java diff --git a/src/org/jgrapht/experimental/equivalence/package.html b/src/org/jgrapht/experimental/equivalence/package.html deleted file mode 100644 index dbc6049..0000000 --- a/src/org/jgrapht/experimental/equivalence/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Classes which enable working with Equivalence Sets. - - diff --git a/src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java deleted file mode 100644 index d60683c..0000000 --- a/src/org/jgrapht/experimental/isomorphism/AbstractExhaustiveIsomorphismInspector.java +++ /dev/null @@ -1,423 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * AbstractExhaustiveIsomorphismInspector.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: AbstractExhaustiveIsomorphismInspector.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.experimental.equivalence.*; -import org.jgrapht.experimental.permutation.*; -import org.jgrapht.util.*; - - -/** - * Abstract base for isomorphism inspectors which exhaustively test the possible - * mappings between graphs. The current algorithms do not support graphs with - * multiple edges (Multigraph / Pseudograph). For the maintainer: The reason is - * the use of GraphOrdering which currently does not support all graph types. - * - * @author Assaf Lehr - * @since May 20, 2005 ver5.3 - */ -abstract class AbstractExhaustiveIsomorphismInspector - implements GraphIsomorphismInspector -{ - //~ Static fields/initializers --------------------------------------------- - - public static EquivalenceComparator - edgeDefaultIsomorphismComparator = - new UniformEquivalenceComparator(); - public static EquivalenceComparator - vertexDefaultIsomorphismComparator = - new UniformEquivalenceComparator(); - - //~ Instance fields -------------------------------------------------------- - - protected EquivalenceComparator> - edgeComparator; - protected EquivalenceComparator> - vertexComparator; - - protected Graph graph1; - protected Graph graph2; - - private PrefetchIterator nextSupplier; - - // kept as member, to ease computations - private GraphOrdering lableGraph1; - private LinkedHashSet graph1VertexSet; - private LinkedHashSet graph2EdgeSet; - private CollectionPermutationIter vertexPermuteIter; - private Set currVertexPermutation; // filled every iteration, used in the - - //~ Constructors ----------------------------------------------------------- - - // result relation. - - /** - * @param graph1 - * @param graph2 - * @param vertexChecker eq. group checker for vertexes. If null, - * UniformEquivalenceComparator will be used as default (always return true) - * @param edgeChecker eq. group checker for edges. If null, - * UniformEquivalenceComparator will be used as default (always return true) - */ - public AbstractExhaustiveIsomorphismInspector( - Graph graph1, - Graph graph2, - - // XXX hb 060128: FOllowing parameter may need Graph - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - this.graph1 = graph1; - this.graph2 = graph2; - - if (vertexChecker != null) { - this.vertexComparator = vertexChecker; - } else { - this.vertexComparator = vertexDefaultIsomorphismComparator; - } - - // Unlike vertexes, edges have better performance, when not tested for - // Equivalence, so if the user did not supply one, use null - // instead of edgeDefaultIsomorphismComparator. - - if (edgeChecker != null) { - this.edgeComparator = edgeChecker; - } - - init(); - } - - /** - * Constructor which uses the default comparators. - * - * @param graph1 - * @param graph2 - * - * @see #AbstractExhaustiveIsomorphismInspector(Graph,Graph,EquivalenceComparator,EquivalenceComparator) - */ - public AbstractExhaustiveIsomorphismInspector( - Graph graph1, - Graph graph2) - { - this( - graph1, - graph2, - edgeDefaultIsomorphismComparator, - vertexDefaultIsomorphismComparator); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Inits needed data-structures , among them: - *
    4. LabelsGraph which is a created in the image of graph1 - *
    5. vertexPermuteIter which is created after the vertexes were divided to - * equivalence groups. This saves order-of-magnitude in performance, because - * the number of possible permutations dramatically decreases. - * - *

      for example: if the eq.group are even/odd - only two groups. A graph - * with consist of 10 nodes of which 5 are even , 5 are odd , will need to - * test 5!*5! (14,400) instead of 10! (3,628,800). - * - *

      besides the EquivalenceComparator`s supplied by the user, we also use - * predefined topological comparators. - */ - private void init() - { - this.nextSupplier = - new PrefetchIterator( - - // XXX hb 280106: I don't understand this warning, yet :-) - new NextFunctor()); - - this.graph1VertexSet = new LinkedHashSet(this.graph1.vertexSet()); - - // vertexPermuteIter will be null, if there is no match - this.vertexPermuteIter = - createPermutationIterator( - this.graph1VertexSet, - this.graph2.vertexSet()); - - this.lableGraph1 = - new GraphOrdering( - this.graph1, - this.graph1VertexSet, - this.graph1.edgeSet()); - - this.graph2EdgeSet = new LinkedHashSet(this.graph2.edgeSet()); - } - - /** - * Creates the permutation iterator for vertexSet2 . The subclasses may make - * either cause it to depend on equality groups or use vertexSet1 for it. - * - * @param vertexSet1 [i] may be reordered - * @param vertexSet2 [i] may not. - * - * @return permutation iterator - */ - protected abstract CollectionPermutationIter createPermutationIterator( - Set vertexSet1, - Set vertexSet2); - - /** - *

      1. Creates a LabelsGraph of graph1 which will serve as a source to all - * the comparisons which will follow. - * - *

      2. extract the edge array of graph2; it will be permanent too. - * - *

      3. for each permutation of the vertexes of graph2, test : - * - *

      3.1. vertices - * - *

      3.2. edges (in labelsgraph) - * - *

      Implementation Notes and considerations: Let's consider a trivial - * example: graph of strings "A","B","C" with two edges A->B,B->C. Let's - * assume for this example that the vertex comparator always returns true, - * meaning String value does not matter, only the graph structure does. So - * "D" "E" "A" with D->E->A will be isomorphic , but "A","B,"C"with - * A->B,A->C will not. - * - *

      First let's extract the important info for isomorphism from the graph. - * We don't care what the vertexes are, we care that there are 3 of them - * with edges from first to second and from second to third. So the source - * LabelsGraph will be: vertexes:[1,2,3] edges:[[1->2],[2->3]] Now we will - * do several permutations of D,E,A. A few examples: D->E , E->A - * [1,2,3]=[A,D,E] so edges are: 2->3 , 3->1 . does it match the source? NO. - * [1,2,3]=[D,A,E] so edges are: 1->3 , 3->2 . no match either. - * [1,2,3]=[D,E,A] so edges are: 1->2 , 2->3 . MATCH FOUND ! Trivial - * algorithm: We will iterate on all permutations - * [abc][acb][bac][bca][cab][cba]. (n! of them,3!=6) For each, first compare - * vertexes using the VertexComparator(always true). Then see that the edges - * are in the exact order 1st->2nd , 2nd->3rd. If we found a match stop and - * return true, otherwise return false; we will compare vetices and edges by - * their order (1st,2nd,3rd,etc) only. Two graphs are the same, by this - * order, if: 1. for each i, sourceVertexArray[i] is equivalent to - * targetVertexArray[i] 2. for each vertex, the edges which start in it (it - * is the source) goes to the same ordered vertex. For multiple ones, count - * them too. - * - * @return IsomorphismRelation for a permutation found, or null if no - * permutation was isomorphic - */ - private IsomorphismRelation findNextIsomorphicGraph() - { - boolean result = false; - IsomorphismRelation resultRelation = null; - if (this.vertexPermuteIter != null) { - // System.out.println("Souce LabelsGraph="+this.lableGraph1); - while (this.vertexPermuteIter.hasNext()) { - currVertexPermutation = this.vertexPermuteIter.getNextSet(); - - // compare vertexes - if (!areVertexSetsOfTheSameEqualityGroup( - this.graph1VertexSet, - currVertexPermutation)) - { - continue; // this one is not iso, so try the next one - } - - // compare edges - GraphOrdering currPermuteGraph = - new GraphOrdering( - this.graph2, - currVertexPermutation, - this.graph2EdgeSet); - - // System.out.println("target LablesGraph="+currPermuteGraph); - if (this.lableGraph1.equalsByEdgeOrder(currPermuteGraph)) { - // create result object. - resultRelation = - new IsomorphismRelation( - new ArrayList(graph1VertexSet), - new ArrayList(currVertexPermutation), - graph1, - graph2); - - // if the edge comparator exists, check equivalence by it - boolean edgeEq = - areAllEdgesEquivalent( - resultRelation, - this.edgeComparator); - if (edgeEq) // only if equivalent - - { - result = true; - break; - } - } - } - } - - if (result == true) { - return resultRelation; - } else { - return null; - } - } - - /** - * Will be called on every two sets of vertexes returned by the permutation - * iterator. From findNextIsomorphicGraph(). Should make sure that the two - * sets are euqivalent. Subclasses may decide to implements it as an always - * true methods only if they make sure that the permutationIterator will - * always be already equivalent. - * - * @param vertexSet1 FIXME Document me - * @param vertexSet2 FIXME Document me - */ - protected abstract boolean areVertexSetsOfTheSameEqualityGroup( - Set vertexSet1, - Set vertexSet2); - - /** - * For each edge in g1, get the Correspondence edge and test the pair. - * - * @param resultRelation - * @param edgeComparator if null, always return true. - */ - protected boolean areAllEdgesEquivalent( - IsomorphismRelation resultRelation, - EquivalenceComparator> edgeComparator) - { - boolean checkResult = true; - - if (edgeComparator == null) { - // nothing to check - return true; - } - - try { - Set edgeSet = this.graph1.edgeSet(); - - for (E currEdge : edgeSet) { - E correspondingEdge = - resultRelation.getEdgeCorrespondence(currEdge, true); - - // if one edge test fail , fail the whole method - if (!edgeComparator.equivalenceCompare( - currEdge, - correspondingEdge, - this.graph1, - this.graph2)) - { - checkResult = false; - break; - } - } - } catch (IllegalArgumentException illegal) { - checkResult = false; - } - - return checkResult; - } - - /** - * return nextElement() casted as IsomorphismRelation - */ - public IsomorphismRelation nextIsoRelation() - { - return next(); - } - - /** - * Efficiency: The value is known after the first check for isomorphism - * activated on this class and returned there after in O(1). If called on a - * new ("virgin") class, it activates 1 iso-check. - * - * @return true iff the two graphs are isomorphic - */ - public boolean isIsomorphic() - { - return !(this.nextSupplier.isEnumerationStartedEmpty()); - } - - /* (non-Javadoc) - * @see java.util.Enumeration#hasMoreElements() - */ - public boolean hasNext() - { - boolean result = this.nextSupplier.hasMoreElements(); - - return result; - } - - /** - * @see java.util.Iterator#next() - */ - public IsomorphismRelation next() - { - return this.nextSupplier.nextElement(); - } - - /* (non-Javadoc) - * @see java.util.Iterator#remove() - */ - public void remove() - { - throw new UnsupportedOperationException( - "remove() method is not supported in AdaptiveIsomorphismInspectorFactory." - + " There is no meaning to removing an isomorphism result."); - } - - //~ Inner Classes ---------------------------------------------------------- - - private class NextFunctor - implements PrefetchIterator.NextElementFunctor - { - public IsomorphismRelation nextElement() - throws NoSuchElementException - { - IsomorphismRelation resultRelation = findNextIsomorphicGraph(); - if (resultRelation != null) { - return resultRelation; - } else { - throw new NoSuchElementException( - "IsomorphismInspector does not have any more elements"); - } - } - } -} - -// End AbstractExhaustiveIsomorphismInspector.java diff --git a/src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java b/src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java deleted file mode 100644 index 1fca285..0000000 --- a/src/org/jgrapht/experimental/isomorphism/AdaptiveIsomorphismInspectorFactory.java +++ /dev/null @@ -1,268 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * AdaptiveIsomorphismInspectorFactory.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: AdaptiveIsomorphismInspectorFactory.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import org.jgrapht.*; -import org.jgrapht.experimental.equivalence.*; -import org.jgrapht.graph.*; - - -/** - * This class serves as a factory for GraphIsomorphismInspector concrete - * implementations. It can be used in two ways: - *

    6. You can can let this class to determine what is the most efficient - * algorithm for your graph. - *
    7. You can specify the type of your graph (planar / tree / other) and save - * this class the graph-checking time. - * - *

      Note that the concrete implementations are package-private and should not - * be created directly. If you are the maintainer of the package, you can add - * new implementation classes, and add them to the "check-list". The current - * algorithms do not support graphs with multiple edges (Multigraph / - * Pseudograph) - * - * @author Assaf - * @see GraphIsomorphismInspector - * @since Jul 17, 2005 - */ -public class AdaptiveIsomorphismInspectorFactory -{ - //~ Static fields/initializers --------------------------------------------- - - public static final int GRAPH_TYPE_ARBITRARY = 0; - public static final int GRAPH_TYPE_PLANAR = 1; - public static final int GRAPH_TYPE_TREE = 2; - public static final int GRAPH_TYPE_MULTIGRAPH = 3; - - //~ Methods ---------------------------------------------------------------- - - /** - * Creates a new inspector, letting this class determine what is the most - * efficient algorithm. - * - * @param graph1 - * @param graph2 - * @param vertexChecker may be null - * @param edgeChecker may be null - */ - public static GraphIsomorphismInspector createIsomorphismInspector( - Graph graph1, - Graph graph2, - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - int graphType = checkGraphsType(graph1, graph2); - return createAppropriateConcreteInspector( - graphType, - graph1, - graph2, - vertexChecker, - edgeChecker); - } - - /** - * Creates a new inspector, letting this class determine what is the most - * efficient algorithm and using default equivalence comparators. - * - *

      same as calling createIsomorphismInspector(graph1,graph2,null,null); - * - * @param graph1 - * @param graph2 - */ - public static GraphIsomorphismInspector createIsomorphismInspector( - Graph graph1, - Graph graph2) - { - return createIsomorphismInspector(graph1, graph2, null, null); - } - - /** - * Creates a new inspector for a particular graph type (planar / tree / - * other). - * - * @param type - AdaptiveIsomorphismInspectorFactory.GRAPH_TYPE_XXX - * @param graph1 - * @param graph2 - * @param vertexChecker - can be null - * @param edgeChecker - can be null - */ - public static GraphIsomorphismInspector - createIsomorphismInspectorByType( - int type, - Graph graph1, - Graph graph2, - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - return createAppropriateConcreteInspector( - type, - graph1, - graph2, - vertexChecker, - edgeChecker); - } - - /** - * Creates a new inspector for a particular graph type (planar / tree / - * other) using default equivalence comparators. - * - *

      same as calling - * createAppropriateConcreteInspector(graph1,graph2,null,null); - * - * @param type - AdaptiveIsomorphismInspectorFactory.GRAPH_TYPE_XXX - * @param graph1 - * @param graph2 - */ - public static GraphIsomorphismInspector - createIsomorphismInspectorByType( - int type, - Graph graph1, - Graph graph2) - { - return createAppropriateConcreteInspector( - type, - graph1, - graph2, - null, - null); - } - - /** - * Checks the graph type, and accordingly decides which type of concrete - * inspector class to create. This implementation creates an exhaustive - * inspector without further tests, because no other implementations are - * available yet. - * - * @param graph1 - * @param graph2 - * @param vertexChecker - * @param edgeChecker - */ - protected static GraphIsomorphismInspector - createAppropriateConcreteInspector( - int graphType, - Graph graph1, - Graph graph2, - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - assertUnsupportedGraphTypes(graph1); - assertUnsupportedGraphTypes(graph2); - GraphIsomorphismInspector currentInspector = null; - - switch (graphType) { - case GRAPH_TYPE_PLANAR: - case GRAPH_TYPE_TREE: - case GRAPH_TYPE_ARBITRARY: - currentInspector = - createTopologicalExhaustiveInspector( - graph1, - graph2, - vertexChecker, - edgeChecker); - break; - - default: - - throw new IllegalArgumentException( - "The type was not one of the supported types."); - } - return currentInspector; - } - - /** - * Checks if one of the graphs is from unsupported graph type and throws - * IllegalArgumentException if it is. The current unsupported types are - * graphs with multiple-edges. - * - * @param graph1 - * @param graph2 - * - * @throws IllegalArgumentException - */ - protected static void assertUnsupportedGraphTypes(Graph g) - throws IllegalArgumentException - { - if ((g instanceof Multigraph) - || (g instanceof DirectedMultigraph) - || (g instanceof Pseudograph)) - { - throw new IllegalArgumentException( - "graph type not supported for the graph" + g); - } - } - - protected static int checkGraphsType(Graph graph1, Graph graph2) - { - return GRAPH_TYPE_ARBITRARY; - } - - /** - * @return ExhaustiveInspector, where the equivalence comparator is chained - * with a topological comparator. This implementation uses: - *

    8. vertex degree size comparator - */ - @SuppressWarnings("unchecked") - protected static GraphIsomorphismInspector - createTopologicalExhaustiveInspector( - Graph graph1, - Graph graph2, - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - VertexDegreeEquivalenceComparator degreeComparator = - new VertexDegreeEquivalenceComparator(); - EquivalenceComparatorChain> vertexChainedChecker = - new EquivalenceComparatorChainBase>( - degreeComparator); - vertexChainedChecker.appendComparator(vertexChecker); - - GraphIsomorphismInspector inspector = - - // FIXME hb060208 I don't understand how to generify this, yet - new EquivalenceIsomorphismInspector( - graph1, - graph2, - vertexChainedChecker, - edgeChecker); - return inspector; - } -} - -// End AdaptiveIsomorphismInspectorFactory.java diff --git a/src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java deleted file mode 100644 index 9a23646..0000000 --- a/src/org/jgrapht/experimental/isomorphism/EquivalenceIsomorphismInspector.java +++ /dev/null @@ -1,325 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * EquivalenceIsomorphismInspector.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: EquivalenceIsomorphismInspector.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.experimental.equivalence.*; -import org.jgrapht.experimental.permutation.*; - - -/** - * The current implementation uses the vertexComparator to greatly increase the - * test speed by dividing the vertexes into equivalent groups and permuting - * inside them only. The EdgeComparator is used to test edges, but not to make a - * finer division, thus it adds overhead. Use it only when needed. - * - * @author Assaf - * @since Jul 29, 2005 - */ -class EquivalenceIsomorphismInspector - extends AbstractExhaustiveIsomorphismInspector -{ - //~ Constructors ----------------------------------------------------------- - - /** - * @param graph1 - * @param graph2 - * @param vertexChecker eq. group checker for vertexes. If null, - * UniformEquivalenceComparator will be used as default (always return true) - * @param edgeChecker eq. group checker for edges. If null, - * UniformEquivalenceComparator will be used as default (always return true) - */ - public EquivalenceIsomorphismInspector( - Graph graph1, - Graph graph2, - - // XXX hb 060128: FOllowing parameter may need Graph - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - super(graph1, graph2, vertexChecker, edgeChecker); - } - - /** - * Constructor which uses the default comparators. - * - * @see ExhaustiveIsomorphismInspector(Graph,Graph,EquivalenceComparator,EquivalenceComparator) - */ - public EquivalenceIsomorphismInspector( - Graph graph1, - Graph graph2) - { - super(graph1, graph2); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Creates the permutation iterator according to equivalance class. - * - *

      1. Get the eq.group (ordered by size) array of the source vertex set - * (vertexSet1) - * - *

      2. Get the eq.group ordered array of vertexSet2. - * - *

      3. Reorder the second array to match the group order of the first - * array sets. 4. Use CompoundPermutationIter (and not regular - * IntegerPermutationIter) to permute only inside groups. - * - *

      - *

      That's it. If the eq.group comaparator is strong enough to provide - * small groups, this algortihm will produce a small possible permutations - * numbers. example: G1: [A,B,F,X,Y] [A->B,B->X,X->Y] - * - *

      G2: [D,Z,C,U,F] [D->C,Z->C,U->Z] - * - *

      vertexEq: three groups , one all letters A-E , second all letters S-Z - * , third the letter 'f'. 1. [(f)size=1, (X,Y)size=2 , (A,B)size=2] 2. - * [(f)size=1 ,(C,D)size=2 , (Z,U)size=2] 3. the match is done by reordering - * the second array to have the equiviavlant order :##[(f)size=1 , - * (Z,U)size=2 , (C,D)size=2]## 4.for example G2 will not do all 5!=120 - * permutations , but 2!x2!x1!=4 permutations only which are: (of the 3rd - * array) [ F, Z , U , C , D ] [ F, Z , U , D , C ] [ F, U , Z, C , D ] [ F, - * U , Z , D , C ] - * - * @return null, if the eq.group do not match (there cannot be any - * permutation for eq.groups) or the sets do not match in size; otherwise, - * the permutationiterator otherwise - * - * @see AbstractExhaustiveIsomorphismInspector#createPermutationIterator(Set, - * Set) - */ - @SuppressWarnings("unchecked") - protected CollectionPermutationIter createPermutationIterator( - Set vertexSet1, - Set vertexSet2) - { - if (vertexSet1.size() != vertexSet2.size()) { - // throw new IllegalArgumentException("the two vertx-sets - // parameters must be of" - // +"the same size. The first size was:"+vertexSet1.size() - // +" the other size was:" +vertexSet2.size() ); - return null; // only instead of exception - } - - // 1// - EquivalenceSet [] eqGroupArray1 = - EquivalenceSetCreator.createEqualityGroupOrderedArray( - vertexSet1, - this.vertexComparator, - this.graph1); - - // 2// - EquivalenceSet [] eqGroupArray2 = - EquivalenceSetCreator.createEqualityGroupOrderedArray( - vertexSet2, - this.vertexComparator, - this.graph2); - - // 3// - boolean reorderSuccess = - reorderTargetArrayToMatchSourceOrder(eqGroupArray1, eqGroupArray2); // 2 is the target - if (!reorderSuccess) { - // if reordering fail , no match can be done - return null; - } - - // reorder set1 (source), so when we work with the flat array of the - // second array, - // the permutations will be relevant. - // note that it does not start in any way related to eqGroup sizes. - - V [] reorderingVertexSet1Temp = (V []) new Object[vertexSet1.size()]; - fillElementsflatArray(eqGroupArray1, reorderingVertexSet1Temp); - vertexSet1.clear(); - vertexSet1.addAll(Arrays.asList(reorderingVertexSet1Temp)); - - // 4//use CompoundPermutationIter to permute only inside groups. - // the CollectionPermutationIter needs a array/set of objects and a - // permuter which will - // work on that set/array order. lets make these two: - // 1. create array of the vertexes , by flattening the eq.group array - // contents - - V [] flatVertexArray = (V []) new Object[vertexSet2.size()]; - fillElementsflatArray(eqGroupArray2, flatVertexArray); - - // 2. make the permuter according to the groups size - int [] groupSizesArray = new int[eqGroupArray1.length]; - - // iterate over the EqualityGroup array - for ( - int eqGroupCounter = 0; - eqGroupCounter < eqGroupArray2.length; - eqGroupCounter++) - { - // now for (.2.) size count - groupSizesArray[eqGroupCounter] = - eqGroupArray2[eqGroupCounter].size(); - } - - ArrayPermutationsIter arrayPermIter = - PermutationFactory.createByGroups(groupSizesArray); - CollectionPermutationIter vertexPermIter = - new CollectionPermutationIter( - Arrays.asList(flatVertexArray), - arrayPermIter); - - return vertexPermIter; - } - - /** - * Reorders inplace targetArray - * - *

      rules: - *

    9. try to match only group of the same size and then hashcode - *
    10. it is enough to choose one from each group to see if a match exist. - * - *

      Algorithm: hold counters in the two arrays. [a,b,c,d,e] assume groups - * are:a,(b,c,d),e [a,c,d,b,e] c1=0 , c2=0 check if eqvivalent . if not , - * advance , as long as both size and hashcode are the same. if found a - * match , swap the group positions in array2. if not , throws - * IllegalArgumentExcpetion. Assumption: array size is the same. not - * checked. - * - * @param sourceArray - * @param targetArray - * - * @return true if the array was reordered successfully. false if not(It - * will happen if there is no complete match between the groups) - */ - private boolean reorderTargetArrayToMatchSourceOrder( - EquivalenceSet [] sourceArray, - EquivalenceSet [] targetArray) - { - boolean result = true; - for ( - int sourceIndex = 0; - sourceIndex < sourceArray.length; - sourceIndex++) - { - int currTargetIndex = sourceIndex; - - // if they are already equivalent do nothing. - EquivalenceSet sourceEqGroup = sourceArray[sourceIndex]; - EquivalenceSet targetEqGroup = targetArray[currTargetIndex]; - if (!sourceEqGroup.equals(targetEqGroup)) { - // iterate through the next group in the targetArray until - // a new size or hashcode is seen - boolean foundMatch = false; - int sourceSize = sourceEqGroup.size(); - int sourceHashCode = sourceEqGroup.hashCode(); - while ( - (targetEqGroup.size() == sourceSize) - && (targetEqGroup.hashCode() == sourceHashCode) - && (currTargetIndex < (targetArray.length - 1))) - { - currTargetIndex++; - targetEqGroup = targetArray[currTargetIndex]; - if (targetEqGroup.equals(sourceEqGroup)) { - foundMatch = true; - - // swap . targetEqGroup will serve as the temp - // variable. - targetArray[currTargetIndex] = targetArray[sourceIndex]; - targetArray[sourceIndex] = targetEqGroup; - } - } - if (!foundMatch) { - // a match was not found - // throw new IllegalArgumentException("could not reorder - // the array , because the groups don`t match"); - result = false; - break; - } - } - } - return result; - } - - /** - * @param eqGroupArray - * @param flatArray an empy array with the proper size - */ - protected void fillElementsflatArray( - EquivalenceSet [] eqGroupArray, - Object [] flatVertexArray) - { - int flatVertexArrayNextFree = 0; // the next free place in the array - - // iterate over the EqualityGroup array - for ( - int eqGroupCounter = 0; - eqGroupCounter < eqGroupArray.length; - eqGroupCounter++) - { - Object [] currGroupArray = eqGroupArray[eqGroupCounter].toArray(); - - // copy this small array to the free place in the big - // flatVertexArray - System.arraycopy( - currGroupArray, // src - 0, // srcPos - flatVertexArray, // dest - flatVertexArrayNextFree, // destPos - currGroupArray.length // length - ); - flatVertexArrayNextFree += currGroupArray.length; - } - } - - /** - * We know for sure, that the sets are alreay checked for equivalence , so - * it will return true without any further checks. - * - * @see AbstractExhaustiveIsomorphismInspector#areVertexSetsOfTheSameEqualityGroup( - * Set, Set) - */ - protected boolean areVertexSetsOfTheSameEqualityGroup( - Set vertexSet1, - Set vertexSet2) - { - return true; - } -} - -// End EquivalenceIsomorphismInspector.java diff --git a/src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java deleted file mode 100644 index 36afff3..0000000 --- a/src/org/jgrapht/experimental/isomorphism/GraphIsomorphismInspector.java +++ /dev/null @@ -1,95 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * GraphIsomorphismInspector.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - - -/** - * Isomorphism Overview - * - *

      Isomorphism is the problem of testing whether two graphs are topologically - * the same. Suppose we are given a collection of graphs and must perform some - * operation on each of them. If we can identify which of the graphs are - * duplicates, they can be discarded so as to avoid redundant work. - * - *

      In Formal Math: Input description: Two graphs, G and H. Problem - * description: Find a (or all) mappings f of the vertices of G to the - * vertices of H such that G and H are identical; i.e. (x,y) is an edge of G iff - * (f(x),f(y)) is an edge of H. - * http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK4/NODE180.HTM. - * - *

      Efficiency: The general algorithm is not polynomial, however - * polynomial algorithms are known for special cases, like acyclic graphs, - * planar graphs etc. There are several heuristic algorithms which gives quite - * good results (polynomial) in general graphs, for most but not all cases. - * - *

      Usage: - * - *

        - *
      1. Choose comparators for the vertexes and edges. You may use the default - * comparator by sending null parameters for them to the constructor. Example: - * Assume Your graphs are of human relations. Each vertex is either a man or a - * woman and also has the person name. You may decide that isomorphism is - * checked according to gender, but not according to the specific name. So you - * will create a comparator that distinguishes vertexes only according to - * gender. - *
      2. Use the isIsomorphic() method as a boolean test for isomorphism - *
      3. Use the Iterator interface to iterate through all the possible - * isomorphism ordering. - *
      - * - * @author Assaf Lehr - * @since Jul 15, 2005 - */ -// REVIEW jvs 5-Sept-2005: Since we're using JDK1.5 now, we should be -// able to declare this as Iterator, correct? Otherwise -// the caller doesn't even know what they're getting back. -public interface GraphIsomorphismInspector - extends Iterator -{ - //~ Methods ---------------------------------------------------------------- - - /** - * @return true iff the two graphs are isomorphic - */ - public boolean isIsomorphic(); -} - -// End GraphIsomorphismInspector.java diff --git a/src/org/jgrapht/experimental/isomorphism/GraphOrdering.java b/src/org/jgrapht/experimental/isomorphism/GraphOrdering.java deleted file mode 100644 index 5aa3333..0000000 --- a/src/org/jgrapht/experimental/isomorphism/GraphOrdering.java +++ /dev/null @@ -1,232 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * GraphOrdering.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Holds graph information as int labels only. vertexes: 1,2,3,4 edges:1->2 , - * 3->4 ,1->1. Implementation as imutable graph by int[] for vetexes and - * LabelsEdge[] for edges. The current algorithms do not support graph with - * multiple edges (Multigraph / Pseudograph). For the maintaner: The reason for - * it is the use of edges sets of LabelsEdge in which the equals checks for - * source and target vertexes. Thus there cannot be two LabelsEdge with the same - * source and target in the same Set. - * - * @author Assaf - * @since May 20, 2005 - */ -public class GraphOrdering -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Holds a mapping between key=V(vertex) and value=Integer(vertex order). It - * can be used for identifying the order of regular vertex/edge. - */ - private Map mapVertexToOrder; - - /** - * Holds a HashSet of all LabelsGraph of the graph. - */ - private Set labelsEdgesSet; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new labels graph according to the regular graph. After its - * creation they will no longer be linked, thus changes to one will not - * affect the other. - * - * @param regularGraph - */ - public GraphOrdering(Graph regularGraph) - { - this(regularGraph, regularGraph.vertexSet(), regularGraph.edgeSet()); - } - - /** - * Creates a new labels graph according to the regular graph. After its - * creation they will no longer be linked, thus changes to one will not - * affect the other. - * - * @param regularGraph - * @param vertexSet - * @param edgeSet - */ - public GraphOrdering( - Graph regularGraph, - Set vertexSet, - Set edgeSet) - { - init(regularGraph, vertexSet, edgeSet); - } - - //~ Methods ---------------------------------------------------------------- - - private void init(Graph g, Set vertexSet, Set edgeSet) - { - // create a map between vertex value to its order(1st,2nd,etc) - // "CAT"=1 "DOG"=2 "RHINO"=3 - - this.mapVertexToOrder = new HashMap(vertexSet.size()); - - int counter = 0; - for (V vertex : vertexSet) { - mapVertexToOrder.put(vertex, new Integer(counter)); - counter++; - } - - // create a friendlier representation of an edge - // by order, like 2nd->3rd instead of B->A - // use the map to convert vertex to order - // on directed graph, edge A->B must be (A,B) - // on undirected graph, edge A-B can be (A,B) or (B,A) - - this.labelsEdgesSet = new HashSet(edgeSet.size()); - for (E edge : edgeSet) { - V sourceVertex = g.getEdgeSource(edge); - Integer sourceOrder = mapVertexToOrder.get(sourceVertex); - int sourceLabel = sourceOrder.intValue(); - int targetLabel = - (mapVertexToOrder.get(g.getEdgeTarget(edge))).intValue(); - - LabelsEdge lablesEdge = new LabelsEdge(sourceLabel, targetLabel); - this.labelsEdgesSet.add(lablesEdge); - - if (g instanceof UndirectedGraph) { - LabelsEdge oppositeEdge = - new LabelsEdge(targetLabel, sourceLabel); - this.labelsEdgesSet.add(oppositeEdge); - } - } - } - - /** - * Tests equality by order of edges - */ - public boolean equalsByEdgeOrder(GraphOrdering otherGraph) - { - boolean result = - this.getLabelsEdgesSet().equals(otherGraph.getLabelsEdgesSet()); - - return result; - } - - public Set getLabelsEdgesSet() - { - return labelsEdgesSet; - } - - /** - * This is the format example: - * - *
      -       mapVertexToOrder=        labelsOrder=
      -     * 
      - */ - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append("mapVertexToOrder="); - - // vertex will be printed in their order - Object [] vertexArray = new Object[this.mapVertexToOrder.size()]; - Set keySet = this.mapVertexToOrder.keySet(); - for (V currVertex : keySet) { - Integer index = this.mapVertexToOrder.get(currVertex); - vertexArray[index.intValue()] = currVertex; - } - sb.append(Arrays.toString(vertexArray)); - sb.append("labelsOrder=").append(this.labelsEdgesSet.toString()); - return sb.toString(); - } - - //~ Inner Classes ---------------------------------------------------------- - - private class LabelsEdge - { - private int source; - private int target; - private int hashCode; - - public LabelsEdge(int aSource, int aTarget) - { - this.source = aSource; - this.target = aTarget; - this.hashCode = - new String(this.source + "" + this.target).hashCode(); - } - - /** - * Checks both source and target. Does not check class type to be fast, - * so it may throw ClassCastException. Careful! - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) - { - LabelsEdge otherEdge = (LabelsEdge) obj; - if ((this.source == otherEdge.source) - && (this.target == otherEdge.target)) - { - return true; - } else { - return false; - } - } - - /** - * @see java.lang.Object#hashCode() - */ - public int hashCode() - { - return this.hashCode; // filled on constructor - } - - public String toString() - { - return this.source + "->" + this.target; - } - } -} - -// End GraphOrdering.java diff --git a/src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java b/src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java deleted file mode 100644 index 1d5fb29..0000000 --- a/src/org/jgrapht/experimental/isomorphism/IsomorphismRelation.java +++ /dev/null @@ -1,151 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * IsomorphismRelation.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - * Holds an isomorphism relation for two graphs. It contains a mapping between - * the two graphs. - * - *

      Usage: - * - *

        - *
      1. use getVertexCorrespondence() or - * getEdgeCorrespondence() to get the mapped object in the other graph. - *
      - * - *

      - *

      It consists of two vertexes array , the i-th vertex in the 1st array is - * the isomorphic eqv. of the i-th in 2nd array. Note that the getters are - * unsafe (they return the array and not a copy of it). - * - * @author Assaf - * @since May 27, 2005 - */ -public class IsomorphismRelation - implements GraphMapping -{ - //~ Instance fields -------------------------------------------------------- - - private List vertexList1; - private List vertexList2; - - private GraphMapping graphMapping = null; - - private Graph graph1; - private Graph graph2; - - //~ Constructors ----------------------------------------------------------- - - /** - */ - public IsomorphismRelation( - List aGraph1vertexArray, - List aGraph2vertexArray, - Graph g1, - Graph g2) - { - this.vertexList1 = aGraph1vertexArray; - this.vertexList2 = aGraph2vertexArray; - this.graph1 = g1; - this.graph2 = g2; - } - - //~ Methods ---------------------------------------------------------------- - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append("vertexList1: ").append( - this.vertexList1.toString()); - sb.append("\tvertexList2: ").append( - this.vertexList2.toString()); - return sb.toString(); - } - - public V getVertexCorrespondence(V vertex, boolean forward) - { - // lazy initializer for graphMapping - if (graphMapping == null) { - initGraphMapping(); - } - - return graphMapping.getVertexCorrespondence(vertex, forward); - } - - public E getEdgeCorrespondence(E edge, boolean forward) - { - // lazy initializer for graphMapping - if (graphMapping == null) { - initGraphMapping(); - } - - return graphMapping.getEdgeCorrespondence(edge, forward); - } - - /** - * We currently have the vertexes array. From them we will construct two - * maps: g1ToG2 and g2ToG1, using the array elements with the same index. - */ - private void initGraphMapping() - { - int mapSize = vertexList1.size(); - Map g1ToG2 = new HashMap(mapSize); - Map g2ToG1 = new HashMap(mapSize); - - for (int i = 0; i < mapSize; i++) { - V source = this.vertexList1.get(i); - V target = this.vertexList2.get(i); - g1ToG2.put(source, target); - g2ToG1.put(target, source); - } - this.graphMapping = - new DefaultGraphMapping( - g1ToG2, - g2ToG1, - this.graph1, - this.graph2); - } -} - -// End IsomorphismRelation.java diff --git a/src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java b/src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java deleted file mode 100644 index c8ad67d..0000000 --- a/src/org/jgrapht/experimental/isomorphism/PermutationIsomorphismInspector.java +++ /dev/null @@ -1,148 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * PermutationIsomorphismInspector.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: PermutationIsomorphismInspector.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.experimental.equivalence.*; -import org.jgrapht.experimental.permutation.*; - - -/** - * Checks every possible permutation. - * - *

      It does not uses the graph topology to enhance the performance. It is - * recommended to use only if there cannot be a useful division into equivalence - * sets. - * - * @author Assaf - * @since Jul 29, 2005 - */ -class PermutationIsomorphismInspector - extends AbstractExhaustiveIsomorphismInspector -{ - //~ Constructors ----------------------------------------------------------- - - /** - * @param graph1 - * @param graph2 - * @param vertexChecker eq. group checker for vertexes. If null, - * UniformEquivalenceComparator will be used as default (always return true) - * @param edgeChecker eq. group checker for edges. If null, - * UniformEquivalenceComparator will be used as default (always return true) - */ - public PermutationIsomorphismInspector( - Graph graph1, - Graph graph2, - - // XXX hb 060128: FOllowing parameter may need Graph - EquivalenceComparator> vertexChecker, - EquivalenceComparator> edgeChecker) - { - super(graph1, graph2, vertexChecker, edgeChecker); - } - - /** - * Constructor which uses the default comparators. - * - * @see AbstractExhaustiveIsomorphismInspector#AbstractExhaustiveIsomorphismInspector(Graph, - * Graph) - */ - public PermutationIsomorphismInspector( - Graph graph1, - Graph graph2) - { - super(graph1, graph2); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Creates the permutation iterator, not dependant on equality group, or the - * other vertexset. - * - * @param vertexSet1 FIXME Document me - * @param vertexSet2 FIXME Document me - * - * @return the permutation iterator - */ - protected CollectionPermutationIter createPermutationIterator( - Set vertexSet1, - Set vertexSet2) - { - return new CollectionPermutationIter(vertexSet2); - } - - /** - * FIXME Document me FIXME Document me - * - * @param vertexSet1 FIXME Document me - * @param vertexSet2 FIXME Document me - * - * @return FIXME Document me - */ - protected boolean areVertexSetsOfTheSameEqualityGroup( - Set vertexSet1, - Set vertexSet2) - { - if (vertexSet1.size() != vertexSet2.size()) { - return false; - } - Iterator iter2 = vertexSet2.iterator(); - - // only check hasNext() of one , cause they are of the same size - for (Iterator iter1 = vertexSet1.iterator(); iter1.hasNext();) { - V vertex1 = iter1.next(); - V vertex2 = iter2.next(); - if (!this.vertexComparator.equivalenceCompare( - vertex1, - vertex2, - this.graph1, - this.graph2)) - { - return false; - } - } - return true; - } -} - -// End PermutationIsomorphismInspector.java diff --git a/src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java b/src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java deleted file mode 100644 index 7275a53..0000000 --- a/src/org/jgrapht/experimental/isomorphism/VertexDegreeEquivalenceComparator.java +++ /dev/null @@ -1,178 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * VertexDegreeEquivalenceComparator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id: VertexDegreeEquivalenceComparator.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.isomorphism; - -import org.jgrapht.*; -import org.jgrapht.experimental.equivalence.*; - - -/** - * Two vertexes are equivalent under this comparator if and only if: - * - *

        - *
      1. they have the same IN degree - * - *

        AND - *

      2. they have the same OUT degree - *
      - * - * @author Assaf - * @since Jul 21, 2005 - */ -public class VertexDegreeEquivalenceComparator - implements EquivalenceComparator> -{ - //~ Constructors ----------------------------------------------------------- - - /** - */ - public VertexDegreeEquivalenceComparator() - { - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Compares the in degrees and the out degrees of the two vertexes. - * - *

      One may reside in an Undirected Graph and the other in a Directed - * graph, or both on the same graph type. - * - * @see EquivalenceComparator#equivalenceCompare(Object, Object, Object, - * Object) - */ - public boolean equivalenceCompare( - V vertex1, - V vertex2, - Graph context1, - Graph context2) - { - // note that VertexDegreeComparator cannot be used. It supports only - // directed graphs. - InOutDegrees inOut1 = getInOutDegrees(context1, vertex1); - InOutDegrees inOut2 = getInOutDegrees(context2, vertex2); - boolean result = inOut1.equals(inOut2); - return result; - } - - /** - * Hashes using the in & out degree of a vertex - * - * @see EquivalenceComparator#equivalenceHashcode(Object, Object) - */ - public int equivalenceHashcode(V vertex, Graph context) - { - InOutDegrees inOut = getInOutDegrees(context, vertex); - - // hash it using the string hash. use the format N '-' N - StringBuffer sb = new StringBuffer(); - sb.append(String.valueOf(inOut.inDegree)); - sb.append("-"); // to diffrentiate inner and outer - sb.append(String.valueOf(inOut.outDegree)); - return sb.toString().hashCode(); - } - - /** - * Calculates the In and Out degrees of vertexes. Supported graph types: - * UnDirectedGraph, DirectedGraph. In UnDirected graph, the in = out (as if - * it was undirected and every edge is both an in and out edge) - * - * @param aContextGraph - * @param vertex - */ - protected InOutDegrees getInOutDegrees(Graph aContextGraph, - V vertex) - { - int inVertexDegree = 0; - int outVertexDegree = 0; - if (aContextGraph instanceof UndirectedGraph) { - UndirectedGraph undirectedGraph = - (UndirectedGraph) aContextGraph; - inVertexDegree = undirectedGraph.degreeOf(vertex); - outVertexDegree = inVertexDegree; // it is UNdirected - } else if (aContextGraph instanceof DirectedGraph) { - DirectedGraph directedGraph = - (DirectedGraph) aContextGraph; - inVertexDegree = directedGraph.inDegreeOf(vertex); - outVertexDegree = directedGraph.outDegreeOf(vertex); - } else { - throw new RuntimeException( - "contextGraph is of unsupported type . It must be one of these two :" - + " UndirectedGraph or DirectedGraph"); - } - return new InOutDegrees(inVertexDegree, outVertexDegree); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Simple structure used to hold the two ints: vertex in degree and vertex - * out degree. Useful as returned value for methods which calculate both at - * the same time. - * - * @author Assaf - * @since Jul 21, 2005 - */ - protected class InOutDegrees - { - public int inDegree; - public int outDegree; - - public InOutDegrees(int aInDegree, int aOutDegree) - { - this.inDegree = aInDegree; - this.outDegree = aOutDegree; - } - - /** - * Checks both inDegree and outDegree. Does not check class type to save - * time. If should be used with caution. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) - { - InOutDegrees other = (InOutDegrees) obj; - return ((this.inDegree == other.inDegree) - && (this.outDegree == other.outDegree)); - } - } -} - -// End VertexDegreeEquivalenceComparator.java diff --git a/src/org/jgrapht/experimental/isomorphism/package.html b/src/org/jgrapht/experimental/isomorphism/package.html deleted file mode 100644 index 07c613f..0000000 --- a/src/org/jgrapht/experimental/isomorphism/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Algorithms which provide isomorphism check between two graphs. - - diff --git a/src/org/jgrapht/experimental/package.html b/src/org/jgrapht/experimental/package.html deleted file mode 100644 index 2a72e67..0000000 --- a/src/org/jgrapht/experimental/package.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -

      A package that contains experimental work or work-in-progress that -is not yet ready to be included in a release. It may contain classes -that are: incomplete, not yet documented, have not yet reached a -satisfying form, etc.

      - -

      The only requirement for classes included here is to compile.

      - - \ No newline at end of file diff --git a/src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java b/src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java deleted file mode 100644 index 6d350bb..0000000 --- a/src/org/jgrapht/experimental/permutation/ArrayPermutationsIter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * ArrayPermutationsIter.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.permutation; - -/** - * An interface to iterate over array permutations. Similiar to Iterator, but - * with specific return types and without the remove() method. - * - * @author Assaf - * @since Jul 29, 2005 - */ -public interface ArrayPermutationsIter -{ - //~ Methods ---------------------------------------------------------------- - - public int [] nextPermutation(); - - public boolean hasNextPermutaions(); -} - -// End ArrayPermutationsIter.java diff --git a/src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java b/src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java deleted file mode 100644 index 11e8071..0000000 --- a/src/org/jgrapht/experimental/permutation/CollectionPermutationIter.java +++ /dev/null @@ -1,185 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * CollectionPermutationIter.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.permutation; - -import java.util.*; - - -/** - * Given a container with elements (Collection,Enumeration,array) defines a - * permutation iterator which returns, on each iteration, a differnt permutation - * of the source container. You may choose a different container - * type(Collection/Array/etc) for each next call. It will continue as if they - * were the same iterator. - * - * @author Assaf - * @since May 20, 2005 - */ -public class CollectionPermutationIter -{ - //~ Instance fields -------------------------------------------------------- - - private ArrayPermutationsIter permOrder; - private List sourceArray; - - /** - * change everry calculation.can be retrieved publicly - */ - private int [] currPermutationArray; - - //~ Constructors ----------------------------------------------------------- - - /** - * Note: the Set interface does not guarantee iteration order. This method - * iterates on the set to get the initial order and after that the data will - * be saved internally in another (ordered) container. So, remeber that the - * Initial order can be different from the objectSet.toString() method. If - * you want it to be the same, use a LinkedHashSet , or use the array - * constructor. - * - * @param objectsSet - */ - public CollectionPermutationIter(Set objectsSet) - { - this( - new ArrayList(objectsSet), - new IntegerPermutationIter(objectsSet.size())); - } - - /** - * Uses a permArray like [1,1,1,2] where some of the permutations are not - * relevant. Here there will be 4 permutations (only the '2' position is - * important) - * - * @param objectsArray - * @param permuter - */ - public CollectionPermutationIter(List objectsArray) - { - this( - objectsArray, - new IntegerPermutationIter(objectsArray.size())); - } - - public CollectionPermutationIter( - List objectsArray, - ArrayPermutationsIter permuter) - { - this.permOrder = permuter; - this.sourceArray = objectsArray; - } - - //~ Methods ---------------------------------------------------------------- - - public boolean hasNext() - { - return this.permOrder.hasNextPermutaions(); - } - - /** - * On first call, returns the source as an array; on any other call - * thereafter, a new permutation - * - * @return null if we overflowed! the array otherwise - */ - public List getNextArray() - { - List permutationResult; // will hold the array result - if (this.permOrder.hasNextPermutaions()) { - this.currPermutationArray = this.permOrder.nextPermutation(); - permutationResult = applyPermutation(); - } else { - permutationResult = null; - } - - return permutationResult; - } - - private List applyPermutation() - { - ArrayList output = new ArrayList(sourceArray); - - // Example : this.sourceArray = ["A","B","C","D"] - // perOrder: = [ 1 , 0 , 3 , 2 ] - // result : = ["B","A","D","C"] - for (int i = 0; i < output.size(); i++) { - output.set( - i, - this.sourceArray.get(this.currPermutationArray[i])); - } - return output; - } - - /** - * Wrap result to a Set. - * - * @return null if we overflowed! the set otherwise - */ - public Set getNextSet() - { - List result = getNextArray(); - if (result == null) { - return null; - } else // wrap in a SET - { - Set resultSet = new LinkedHashSet(result); - return resultSet; - } - } - - public int [] getCurrentPermutationArray() - { - return this.currPermutationArray; - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append("Permutation int[]="); - sb.append(Arrays.toString(getCurrentPermutationArray())); - - List permutationResult = applyPermutation(); - sb.append("\nPermutationSet Source Object[]="); - sb.append(this.sourceArray.toString()); - sb.append("\nPermutationSet Result Object[]="); - sb.append(permutationResult.toString()); - return sb.toString(); - } -} - -// End CollectionPermutationIter.java diff --git a/src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java b/src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java deleted file mode 100644 index c988698..0000000 --- a/src/org/jgrapht/experimental/permutation/CompoundPermutationIter.java +++ /dev/null @@ -1,307 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * CompoundPermutationIter.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.permutation; - -import java.util.*; - -import org.jgrapht.util.*; - - -/** - * For permutation like this: - *
    11. 1,2 are the same eq.group (numbers) - *
    12. a,b are og the same eq.group (letters) - *
    13. '$' is of its own eq. group (signs) Let the order of the group be - * (arbitrary): signs,numbers,letters (note that for performance reasons, this - * arbitrary order is the worst! see Performance section below) - * - *

      These are the possible compound perm: [$,1,2,a,b,c] - * - *

      [$,1,2,a,c,b] - * - *

      [$,1,2,b,a,c] - * - *

      [$,1,2,b,c,a] - * - *

      [$,1,2,c,a,b] - * - *

      [$,1,2,c,b,a] - * - *

      [$,2,1,a,b,c] - * - *

      [$,2,1,a,c,b] - * - *

      [$,2,1,b,a,c] - * - *

      [$,2,1,b,c,a] - * - *

      [$,2,1,c,a,b] - * - *

      [$,2,1,c,b,a] - * - *

      The overall number is the product of the factorials of each eq. group - * size; in our example : (1!)x(2!)x(3!)=1x2x6=12. Using the constructor with - * eq.group sizes and initial order [1,2,3], the result permutations are - * retrieved as numbers in an array, where [0,1,2,3,4,5] means [$,1,2,a,b,c]: - * - *

      [0,1,2,3,5,4] - * - *

      [0,1,2,4,3,5] - * - *

      etc. etc., till: - * - *

      [0,2,1,5,4,3] means [$,2,1,c,b,a] - * - *

      - *

      Performance: The implementation tries to advance each time the - * group zero, if it does not succeed, it tries the next group (1,2 and so on), - * so: try to put the largest group as the first groups, UNLIKE the example. - * Performance-wise it is better to do [a,b,c,1,2,$] .The effect is improvement - * by constant (for example, by 2) - * - * @author Assaf - * @since May 30, 2005 - */ -public class CompoundPermutationIter - implements ArrayPermutationsIter, - Iterator -{ - //~ Instance fields -------------------------------------------------------- - - IntegerPermutationIter [] permArray; - - /** - * on the example 1+2+3=6 - */ - private int totalPermArraySize; - - /** - * The overall number is the product of the factorial of each eq. group - * size. - */ - private int max; - - private int iterCounter = 0; - - //~ Constructors ----------------------------------------------------------- - - /** - * For the class example, use [1,2,2]. order matters! (performance-wise too) - * - * @param equalityGroupsSizesArray - */ - public CompoundPermutationIter(int [] equalityGroupsSizesArray) - { - init(equalityGroupsSizesArray); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Creates an IntegerPermutationIter class per equalityGroup with different - * integers. - * - * @param equalityGroupsSizesArray - */ - private void init(int [] equalityGroupsSizesArray) - { - this.permArray = - new IntegerPermutationIter[equalityGroupsSizesArray.length]; - - int counter = 0; - this.max = 1; // each time , multiply by factorail(eqGroupSize) - for ( - int eqGroup = 0; - eqGroup < equalityGroupsSizesArray.length; - eqGroup++) - { - // create an array of eq.group size filled with values - // of counter, counter+1, ... counter+size-1 - int currGroupSize = equalityGroupsSizesArray[eqGroup]; - int [] currArray = new int[currGroupSize]; - for (int i = 0; i < currGroupSize; i++) { - currArray[i] = counter; - counter++; - } - this.permArray[eqGroup] = new IntegerPermutationIter(currArray); - this.permArray[eqGroup].getNext(); // first iteration return the - // source - - // each time , multiply by factorail(eqGroupSize) - this.max *= MathUtil.factorial(currGroupSize); - } - this.totalPermArraySize = counter; - - // calc max - } - - public Object next() - { - return getNext(); - } - - /** - * Iteration may be one of these two: 1. the last group advances by one - * iter, all else stay. 2. the last group cannot advance , so it restarts - * but telling the group after it to advance (done recursively till some - * group can advance) - */ - public int [] getNext() - { - if (this.iterCounter == 0) { - // just return it , without change - this.iterCounter++; - return getPermAsArray(); - } - - int firstGroupCapableOfAdvancing = -1; - int currGroupIndex = 0; // - while (firstGroupCapableOfAdvancing == -1) { - IntegerPermutationIter currGroup = this.permArray[currGroupIndex]; - - if (currGroup.hasNext()) { - currGroup.getNext(); - - // restart all that we passed on - for (int i = 0; i < currGroupIndex; i++) { - restartPermutationGroup(i); - } - firstGroupCapableOfAdvancing = currGroupIndex; - } - - currGroupIndex++; - if (currGroupIndex >= this.permArray.length) { - break; - } - } - - this.iterCounter++; - - if (firstGroupCapableOfAdvancing == -1) { - // nothing found. we finished all iterations - return null; - } else { - int [] tempArray = getPermAsArray(); - return tempArray; - } - } - - /** - * Creates and returns a new array which consists of the eq. group current - * permutation arrays. For example, in the 10th iter ([$,2,1,b,c,a]) The - * permutations current statuses is [0] [2,1] [4,5,3] so retrieve - * [0,2,1,4,5,3] - */ - public int [] getPermAsArray() - { - int [] resultArray = new int[this.totalPermArraySize]; - int counter = 0; - for ( - int groupIndex = 0; - groupIndex < this.permArray.length; - groupIndex++) - { - int [] currPermArray = this.permArray[groupIndex].getCurrent(); - System.arraycopy( - currPermArray, - 0, - resultArray, - counter, - currPermArray.length); - counter += currPermArray.length; - } - return resultArray; - } - - /** - * Restarts by creating a new one instead. - * - * @param groupIndex - */ - private void restartPermutationGroup(int groupIndex) - { - int [] oldPermArray = this.permArray[groupIndex].getCurrent(); - Arrays.sort(oldPermArray); - this.permArray[groupIndex] = new IntegerPermutationIter(oldPermArray); - this.permArray[groupIndex].getNext(); - } - - public boolean hasNext() - { - boolean result; - if (this.iterCounter < this.max) { - result = true; - } else { - result = false; - } - return result; - } - - public int getMax() - { - return max; - } - - /* (non-Javadoc) - * @see ArrayPermutationsIter#nextPermutation() - */ - public int [] nextPermutation() - { - return (int []) next(); - } - - /* (non-Javadoc) - * @see ArrayPermutationsIter#hasNextPermutaions() - */ - public boolean hasNextPermutaions() - { - return hasNext(); - } - - /** - * UNIMPLEMENTED. always throws new UnsupportedOperationException - * - * @see java.util.Iterator#remove() - */ - public void remove() - { - throw new UnsupportedOperationException(); - } -} - -// End CompoundPermutationIter.java diff --git a/src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java b/src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java deleted file mode 100644 index 55fb14a..0000000 --- a/src/org/jgrapht/experimental/permutation/IntegerPermutationIter.java +++ /dev/null @@ -1,311 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * IntegerPermutationIter.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.permutation; - -import java.util.*; - - -/** - * Iterates through permutations of N elements. - *

    14. use getNext() to get the next permutation order, for example(N=4): - * perm0=[1,2,3,4] perm1=[1,2,4,3] perm2=[1,3,2,4] . - *
    15. use hasNext() or verify by counter[1,1,1,2,3]; - * note that there are much less than 5! premutations here, because of the - * repetitive 1s. - * - * @param array creates a copy of it (so sort / later changes will not - * matter) - */ - public IntegerPermutationIter(int [] array) - { - int [] newArray = new int[array.length]; - System.arraycopy(array, 0, newArray, 0, array.length); - Arrays.sort(newArray); - init(newArray); - } - - //~ Methods ---------------------------------------------------------------- - - private void init(int [] array) - { - this.N = array.length; - this.Value = array; - this.currentValueBackup = this.Value; - permutationCounter = 0; - } - - /** - * Swaps by array indexes - * - * @param i - * @param j - */ - private void swap(int i, int j) - { - int temp = this.Value[i]; - this.Value[i] = this.Value[j]; - this.Value[j] = temp; - } - - private int [] arrayClone(int [] sourceArray) - { - int [] destArray = new int[sourceArray.length]; - System.arraycopy(sourceArray, 0, destArray, 0, sourceArray.length); - return destArray; - } - - private int [] getNextStartingWith2() - { - permutationCounter++; - int i = N - 1; - - if (i <= 0) // may happen only on N<=1 - - { - this.endWasReached = true; - return null; - } - - /** while (Value[i-1] >= Value[i]) - { - i = i-1; - }*/ - while (Value[i - 1] >= Value[i]) { - i = i - 1; - if (i == 0) { - this.endWasReached = true; - return null; - } - } - - int j = N; - - while (Value[j - 1] <= Value[i - 1]) { - j = j - 1; - } - - swap(i - 1, j - 1); // swap values at positions (i-1) and (j-1) - - i++; - j = N; - - while (i < j) { - swap(i - 1, j - 1); - i++; - j--; - } - return this.Value; - } - - /** - * Efficiency: O(N) implementation, try to take the next! - */ - public boolean hasNext() - { - if ((this.permutationCounter == 0) - || (this.wasNextValueCalculatedAlready)) - { - return true; - } else if (this.endWasReached) { - return false; - } - - boolean result = true; - // calculate the next value into this.value save the current result. in - // the end swap the arrays there is no way to know when to stop , but - // the out-of-bound - /* try - * { - * this.wasNextValueCalculatedAlready=true; - * getNextStartingWith2(); - * } - * catch (ArrayIndexOutOfBoundsException outOfBoundException) - * { - * endWasReached=true; - * result=false; - * }*/ - - getNextStartingWith2(); - this.wasNextValueCalculatedAlready = true; - if (endWasReached) { - return false; - } - - ////////////////////////////// - return result; - } - - public Object next() - { - return getNext(); - } - - /** - * Facade. use it with getNext. efficency: O(N) - * - * @return a new Array with the permutatation order. for example: - * perm0=[1,2,3,4] perm1=[1,2,4,3] perm2=[1,3,2,4] - */ - public int [] getNext() - { - if (!hasNext()) { - throw new RuntimeException( - "IntegerPermutationIter exceeds the total number of permutaions." - + " Suggestion: do a check with hasNext() , or count till getTotalNumberOfPermutations" - + " before using getNext()"); - } - - // if it is the first one , return original - int [] internalArray; - if (this.permutationCounter == 0) { - this.permutationCounter++; - internalArray = this.Value; - } else { - // if hasNext() has precaclulated it , take this value. - if (this.wasNextValueCalculatedAlready) { - internalArray = this.Value; - this.wasNextValueCalculatedAlready = false; - } else { - internalArray = getNextStartingWith2(); - if (this.endWasReached) { - return null; - } - } - } - this.currentValueBackup = arrayClone(internalArray); - return arrayClone(internalArray); - } - - public int [] getCurrent() - { - return arrayClone(this.currentValueBackup); - } - - /** - * Utility method to convert the array into a string examples: [] [0] - * [0,1][1,0] - * - * @param array - */ - public String toString(int [] array) - { - if (array.length <= 0) { - return "[]"; - } - StringBuffer stBuffer = new StringBuffer("["); - for (int i = 0; i < (array.length - 1); i++) { - stBuffer.append(array[i]).append(","); - } - stBuffer.append(array[array.length - 1]).append("]"); - return stBuffer.toString(); - } - - /** - * UNIMPLEMENTED. always throws new UnsupportedOperationException - * - * @see java.util.Iterator#remove() - */ - public void remove() - { - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see ArrayPermutationsIter#nextPermutation() - */ - public int [] nextPermutation() - { - return (int []) next(); - } - - /* (non-Javadoc) - * @see ArrayPermutationsIter#hasNextPermutaions() - */ - public boolean hasNextPermutaions() - { - return hasNext(); - } -} - -// End IntegerPermutationIter.java diff --git a/src/org/jgrapht/experimental/permutation/PermutationFactory.java b/src/org/jgrapht/experimental/permutation/PermutationFactory.java deleted file mode 100644 index 540df61..0000000 --- a/src/org/jgrapht/experimental/permutation/PermutationFactory.java +++ /dev/null @@ -1,98 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * PermutationFactory.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.experimental.permutation; - -/** - * Factory to create Permutations of several types and use them as Enumerations. - * Note that callers may use them directly if they need to use special concrete - * methods. - * - *

      These types are: - * - *

      - *

    16. All elements are different. There are N! possible permutations. - * - *

      example: source=[1,2,3] - * result=[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2][3,2,1] - * - *

      - *

    17. Some of the elements are the same. - * - *

      example: source=[1,1,2] result=[1,1,2][1,2,1][2,1,1] - * - *

      - *

    18. There are separate permutations groups, which are connected to one - * sequence. Permutations are allowed only inside the group. Possible sequences: - * product of factorial of each group. see example. - * - *

      example: assume source=the groups are sizes are : 1,2,2,5 elements - * will be created: (1),(2,3),(4,5). - * - *

      result=[1,(2,3),(4,5)] [1,(2,3),(5,4)] [1,(3,2),(5,4)] [1,(3,2),(4,5)]. In - * this example the number of possiblities is 1! x 2! x 2! = 4 - * - * @author Assaf Lehr - * @since Jun 3, 2005 - */ -public class PermutationFactory -{ - //~ Methods ---------------------------------------------------------------- - - public static ArrayPermutationsIter createRegular(int [] permSourceArray) - { - IntegerPermutationIter regularPerm = - new IntegerPermutationIter(permSourceArray); - return regularPerm; - } - - /** - * For efficiency, try putting the biggest groups at the beggining of the - * array. - * - * @param groupSizesArray . example [3,2] will create an array (0,1,2)(3,4) - */ - public static ArrayPermutationsIter createByGroups( - int [] groupSizesArray) - { - CompoundPermutationIter complexPerm = - new CompoundPermutationIter(groupSizesArray); - return complexPerm; - } -} - -// End PermutationFactory.java diff --git a/src/org/jgrapht/experimental/permutation/package.html b/src/org/jgrapht/experimental/permutation/package.html deleted file mode 100644 index 82cd61f..0000000 --- a/src/org/jgrapht/experimental/permutation/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Classes to provide all the possible permutations of arrays or sets. - - diff --git a/src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java b/src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java deleted file mode 100644 index 857cf13..0000000 --- a/src/org/jgrapht/generate/CompleteBipartiteGraphGenerator.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * CompleteBipartiteGraphGenerator.java - * ------------------- - * (C) Copyright 2008-2008, by Andrew Newell and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 24-Dec-2008 : Initial revision (AN); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a complete - * bipartite graph of any size. This is a graph with two partitions; two - * vertices will contain an edge if and only if they belong to different - * partitions. - * - * @author Andrew Newell - * @since Dec 21, 2008 - */ -public class CompleteBipartiteGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int sizeA, sizeB; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new CompleteBipartiteGraphGenerator object. - * - * @param partitionOne This is the number of vertices in the first partition - * @param partitionTwo This is the number of vertices in the second parition - */ - public CompleteBipartiteGraphGenerator(int partitionOne, int partitionTwo) - { - if ((partitionOne < 0) || (partitionTwo < 0)) { - throw new IllegalArgumentException("must be non-negative"); - } - this.sizeA = partitionOne; - this.sizeB = partitionTwo; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Construct a complete bipartite graph - */ - public void generateGraph( - Graph target, - final VertexFactory vertexFactory, - Map resultMap) - { - if ((sizeA < 1) && (sizeB < 1)) { - return; - } - - //Create vertices in each of the partitions - Set a = new HashSet(); - Set b = new HashSet(); - for (int i = 0; i < sizeA; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - a.add(newVertex); - } - for (int i = 0; i < sizeB; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - b.add(newVertex); - } - - //Add an edge for each pair of vertices in different partitions - for (Iterator iterA = a.iterator(); iterA.hasNext();) { - V v = iterA.next(); - for (Iterator iterB = b.iterator(); iterB.hasNext();) { - target.addEdge(v, iterB.next()); - } - } - } -} - -// End CompleteBipartiteGraphGenerator.java diff --git a/src/org/jgrapht/generate/CompleteGraphGenerator.java b/src/org/jgrapht/generate/CompleteGraphGenerator.java deleted file mode 100755 index 96e4cfe..0000000 --- a/src/org/jgrapht/generate/CompleteGraphGenerator.java +++ /dev/null @@ -1,139 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * CompleteGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by Tim Shearouse and Contributors. - * - * Original Author: Tim Shearouse - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 10-Feb-2008 : Initial revision (TS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a complete graph of any size. A complete graph is a graph where - * every vertex shares an edge with every other vertex. If it is a directed - * graph, then edges must always exist in both directions. On a side note, a - * complete graph is the least efficient possible graph in terms of memory and - * cpu usage. Note: This contructor was designed for a simple undirected or - * directed graph. It will act strangely when used with certain graph types, - * such as undirected multigraphs. Note, though, that a complete undirected - * multigraph is rather senseless -- you can keep adding edges and the graph is - * never truly complete. - * - * @author Tim Shearouse - * @since Nov 02, 2008 - */ -public class CompleteGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int size; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new CompleteGraphGenerator. - * - * @param size number of vertices to be generated - * - * @throws IllegalArgumentException if the specified size is negative. - */ - public CompleteGraphGenerator(int size) - { - if (size < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - this.size = size; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - if (size < 1) { - return; - } - - //Add all the vertices to the set - for (int i = 0; i < size; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - } - - /* - * We want two iterators over the vertex set, one fast and one slow. - * The slow one will move through the set once. For each vertex, - * the fast iterator moves through the set, adding an edge to all - * vertices we haven't connected to yet. - * - * If we have an undirected graph, the second addEdge call will return - * nothing; it will not add a second edge. - */ - Iterator slowI = target.vertexSet().iterator(); - Iterator fastI; - - while (slowI.hasNext()) { //While there are more vertices in the set - - V latestVertex = slowI.next(); - fastI = target.vertexSet().iterator(); - - //Jump to the first vertex *past* latestVertex - while (fastI.next() != latestVertex) { - ; - } - - //And, add edges to all remaining vertices - V temp; - while (fastI.hasNext()) { - temp = fastI.next(); - target.addEdge(latestVertex, temp); - target.addEdge(temp, latestVertex); - } - } - } -} - -// End CompleteGraphGenerator.java diff --git a/src/org/jgrapht/generate/EmptyGraphGenerator.java b/src/org/jgrapht/generate/EmptyGraphGenerator.java deleted file mode 100644 index 21d6300..0000000 --- a/src/org/jgrapht/generate/EmptyGraphGenerator.java +++ /dev/null @@ -1,95 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * EmptyGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates an empty - * graph of any size. An empty graph is a graph that has no edges. - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public class EmptyGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int size; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new EmptyGraphGenerator. - * - * @param size number of vertices to be generated - * - * @throws IllegalArgumentException if the specified size is negative. - */ - public EmptyGraphGenerator(int size) - { - if (size < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - this.size = size; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - for (int i = 0; i < size; ++i) { - target.addVertex(vertexFactory.createVertex()); - } - } -} - -// End EmptyGraphGenerator.java diff --git a/src/org/jgrapht/generate/GraphGenerator.java b/src/org/jgrapht/generate/GraphGenerator.java deleted file mode 100644 index 105869f..0000000 --- a/src/org/jgrapht/generate/GraphGenerator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * GraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * GraphGenerator defines an interface for generating new graph structures. - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public interface GraphGenerator -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Generate a graph structure. The topology of the generated graph is - * dependent on the implementation. For graphs in which not all vertices - * share the same automorphism equivalence class, the generator may produce - * a labeling indicating the roles played by generated elements. This is the - * purpose of the resultMap parameter. For example, a generator for a wheel - * graph would designate a hub vertex. Role names used as keys in resultMap - * should be declared as public static final Strings by implementation - * classes. - * - * @param target receives the generated edges and vertices; if this is - * non-empty on entry, the result will be a disconnected graph since - * generated elements will not be connected to existing elements - * @param vertexFactory called to produce new vertices - * @param resultMap if non-null, receives implementation-specific mappings - * from String roles to graph elements (or collections of graph elements) - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap); -} - -// End GraphGenerator.java diff --git a/src/org/jgrapht/generate/GridGraphGenerator.java b/src/org/jgrapht/generate/GridGraphGenerator.java deleted file mode 100644 index adb5659..0000000 --- a/src/org/jgrapht/generate/GridGraphGenerator.java +++ /dev/null @@ -1,145 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2011, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * StarGraphGenerator.java - * ------------------- - * (C) Copyright 2011-2011, by Assaf Mizrachi and Contributors. - * - * Original Author: Assaf Mizrachi - * Contributor(s): - - * - * $Id: StarGraphGenerator.java 651 2008-12-24 21:13:41Z perfecthash $ - * - * Changes - * ------- - * 3-Jan-2011 : Initial revision (AM); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a bidirectional grid graph of any - * size. A grid graph is a two dimensional graph whose vertices correspond to - * the points in the plane with integer coordinates, x-coordinates being in the - * range 0,..., n, y-coordinates being in the range 1,...m, and two vertices are - * connected by an edge whenever the corresponding points are at distance 1. - * Vertices are created from left to right and from top to bottom. - * - * @author Assaf Mizrachi - * @since Dec 29, 2010 - */ -public class GridGraphGenerator - implements GraphGenerator -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Role for the vertices at the corners. - */ - public static final String CORNER_VERTEX = "Corner Vertex"; - - //~ Instance fields -------------------------------------------------------- - - private int rows; - - private int cols; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new GridGraphGenerator object with rows x cols dimension. - * - * @param rows the number of rows - * @param cols the number of columns - */ - public GridGraphGenerator(int rows, int cols) - { - if (rows < 2) { - throw new IllegalArgumentException( - "illegal number of rows (" + rows - + "). there must be at least two."); - } - if (cols < 2) { - throw new IllegalArgumentException( - "illegal number of columns (" + cols - + "). there must be at least two."); - } - this.rows = rows; - this.cols = cols; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - @Override public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - Map map = new TreeMap(); - - // Adding all vertices to the set - int cornerCtr = 0; - for (int i = 0; i < (rows * cols); i++) { - V vertex = vertexFactory.createVertex(); - target.addVertex(vertex); - map.put(i + 1, vertex); - - boolean isCorner = - (i == 0) || (i == (cols - 1)) || (i == (cols * (rows - 1))) - || (i == ((rows * cols) - 1)); - if (isCorner && (resultMap != null)) { - resultMap.put(CORNER_VERTEX + ' ' + ++cornerCtr, vertex); - } - } - - // Iterating twice over the key set, for undirected graph edges are - // added from upper vertices to lower, and from left to right. The - // second addEdge call will return nothing; it will not add a the edge - // at the opposite direction. For directed graph, edges in opposite - // direction are also added. - for (int i : map.keySet()) { - for (int j : map.keySet()) { - if ((((i % cols) > 0) - && ((i + 1) == Integer.valueOf(j))) - || ((i + cols) == j)) - { - target.addEdge(map.get(i), map.get(j)); - target.addEdge(map.get(j), map.get(i)); - } - } - } - } -} - -// End GridGraphGenerator.java diff --git a/src/org/jgrapht/generate/HyperCubeGraphGenerator.java b/src/org/jgrapht/generate/HyperCubeGraphGenerator.java deleted file mode 100644 index e58e714..0000000 --- a/src/org/jgrapht/generate/HyperCubeGraphGenerator.java +++ /dev/null @@ -1,118 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * HyperCubeGraphGenerator.java - * ------------------- - * (C) Copyright 2008-2008, by Andrew Newell and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 24-Dec-2008 : Initial revision (AN); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a hyper - * cube graph of any size. This is a graph that can be represented by bit - * strings, so for an n-dimensial hypercube each vertex resembles an n-length - * bit string. Then, two vertices are adjacent if and only if their bitstring - * differ by exactly one element. - * - * @author Andrew Newell - * @since Dec 21, 2008 - */ -public class HyperCubeGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int dim; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new HyperCubeGraphGenerator object. - * - * @param dim This is the dimension of the hypercube. - */ - public HyperCubeGraphGenerator(int dim) - { - this.dim = dim; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * This will generate the hypercube graph - */ - public void generateGraph( - Graph target, - final VertexFactory vertexFactory, - Map resultMap) - { - //Vertices are created, and they are included in the resultmap as their - //bitstring representation - int order = (int) Math.pow(2, dim); - LinkedList vertices = new LinkedList(); - for (int i = 0; i < order; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - vertices.add(newVertex); - if (resultMap != null) { - String s = Integer.toBinaryString(i); - while (s.length() < dim) { - s = "0" + s; - } - resultMap.put(s, newVertex); - } - } - - //Two vertices will have an edge if their bitstrings differ by exactly - //1 element - for (int i = 0; i < order; i++) { - for (int j = i + 1; j < order; j++) { - for (int z = 0; z < dim; z++) { - if ((j ^ i) == (1 << z)) { - target.addEdge(vertices.get(i), vertices.get(j)); - break; - } - } - } - } - } -} - -// End HyberCubeGraphGenerator.java diff --git a/src/org/jgrapht/generate/LinearGraphGenerator.java b/src/org/jgrapht/generate/LinearGraphGenerator.java deleted file mode 100644 index b0b676e..0000000 --- a/src/org/jgrapht/generate/LinearGraphGenerator.java +++ /dev/null @@ -1,124 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * LinearGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a linear graph of any size. For a directed graph, the edges are - * oriented from START_VERTEX to END_VERTEX. - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public class LinearGraphGenerator - implements GraphGenerator -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Role for the first vertex generated. - */ - public static final String START_VERTEX = "Start Vertex"; - - /** - * Role for the last vertex generated. - */ - public static final String END_VERTEX = "End Vertex"; - - //~ Instance fields -------------------------------------------------------- - - private int size; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new LinearGraphGenerator. - * - * @param size number of vertices to be generated - * - * @throws IllegalArgumentException if the specified size is negative. - */ - public LinearGraphGenerator(int size) - { - if (size < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - this.size = size; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - V lastVertex = null; - - for (int i = 0; i < size; ++i) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - - if (lastVertex == null) { - if (resultMap != null) { - resultMap.put(START_VERTEX, newVertex); - } - } else { - target.addEdge(lastVertex, newVertex); - } - - lastVertex = newVertex; - } - - if ((resultMap != null) && (lastVertex != null)) { - resultMap.put(END_VERTEX, lastVertex); - } - } -} - -// End LinearGraphGenerator.java diff --git a/src/org/jgrapht/generate/RandomGraphGenerator.java b/src/org/jgrapht/generate/RandomGraphGenerator.java deleted file mode 100644 index b55bf5a..0000000 --- a/src/org/jgrapht/generate/RandomGraphGenerator.java +++ /dev/null @@ -1,381 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * RandomGraphGenerator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - * This Generator creates a random-topology graph of a specified number of - * vertexes and edges. An instance of this generator will always return the same - * graph-topology in calls to generateGraph(). The vertexes can be different - * (depends on the VertexFactory implementation) - * - *

      However, two instances which use the same constructor parameters will - * produce two different random graphs (note: as with any random generator, - * there is always a small possibility that two instances will create the same - * results). - * - * @author Assaf Lehr - * @since Aug 6, 2005 - */ -public class RandomGraphGenerator - implements GraphGenerator -{ - //~ Static fields/initializers --------------------------------------------- - - private static long seedUniquifier = 8682522807148012L; - - //~ Instance fields -------------------------------------------------------- - - protected int numOfVertexes; - protected int numOfEdges; - protected Random randomizer; - private long randomizerSeed; - - //~ Constructors ----------------------------------------------------------- - - public RandomGraphGenerator(int aNumOfVertexes, int aNumOfEdges) - { - if ((aNumOfVertexes < 0) || (aNumOfEdges < 0)) { - throw new IllegalArgumentException("must be non-negative"); - } - this.numOfVertexes = aNumOfVertexes; - this.numOfEdges = aNumOfEdges; - - this.randomizerSeed = chooseRandomSeedOnce(); - this.randomizer = new Random(this.randomizerSeed); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Should be called only once on creation. Chooses a seed which can be used - * later to reset the randomizer before each method call. This - * implementation copies the java.util.Random constructor because there is - * no getSeed() there, and seed is protected. - * - * @author Assaf - * @since Aug 6, 2005 - */ - private synchronized static long chooseRandomSeedOnce() - { - return (++seedUniquifier + System.nanoTime()); - } - - /** - * Resets seed to generate the same random stream. - */ - private void resetRandomSeed() - { - this.randomizer.setSeed(this.randomizerSeed); - } - - /** - * (non-Javadoc) - * - * @throws IllegalArgumentException if the aNumOfEdges passed in the - * constructor, cannot be created on a graph of the concrete type with - * aNumOfVertexes. - * org.jgrapht.generate.RandomGraphGenerator.DefaultEdgeTopologyFactory#isNumberOfEdgesValid(org.jgrapht.Graph, - * int) - * - * @see GraphGenerator#generateGraph(Graph, VertexFactory, Map) - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - resetRandomSeed(); - - // key = generation order (1st,2nd,3rd,...) value=vertex Object - // will be used later - Map orderToVertexMap = - new HashMap(this.numOfVertexes); - - for (int i = 0; i < this.numOfVertexes; i++) { - V currVertex = vertexFactory.createVertex(); - target.addVertex(currVertex); - orderToVertexMap.put(Integer.valueOf(i), currVertex); - } - - if (target.vertexSet().size() != numOfVertexes) { - throw new IllegalArgumentException( - "Vertex factory did not produce " + numOfVertexes - + " distinct vertices."); - } - - // use specific type of edge factory, depending of the graph type - // and edge density - EdgeTopologyFactory edgesFactory = - edgeTopologyFactoryChooser(target, numOfEdges); - if (!edgesFactory.isNumberOfEdgesValid(target, numOfEdges)) { - throw new IllegalArgumentException( - "numOfEdges is not valid for the graph type " - + "\n-> Invalid number Of Edges=" + numOfEdges + " for:" - + " graph type=" + target.getClass() - + " ,number Of Vertexes=" + this.numOfVertexes - + "\n-> Advice: For the Max value , check the javadoc for" - + " org.jgrapht.generate.RandomGraphGenerator.DefaultEdgeTopologyFactory"); - } - - edgesFactory.createEdges( - target, - orderToVertexMap, - this.numOfEdges, - this.randomizer); - } - - /** - * Returns a concrete EdgeTopologyFactory, depending on graph type and - * numOfEdges - * - * @param target - * - * @return - */ - private EdgeTopologyFactory edgeTopologyFactoryChooser( - Graph target, - int numOfEdges) - { - return new DefaultEdgeTopologyFactory(); - } - - //~ Inner Interfaces ------------------------------------------------------- - - /** - * This class is used to generate the edge topology for a graph. - * - * @author Assaf - * @since Aug 6, 2005 - */ - public interface EdgeTopologyFactory - { - /** - * Two different calls to the createEdges() with the same parameters - * must result in the generation of the same. But if the randomizer is - * different, it should, usually, create different edge topology. - * - * @param targetGraph - guranteed to start with zero edges. - * @param orderToVertexMap - key=Integer of vertex order . between zero - * to numOfVertexes (exclusive). value = vertex from the graph. unique. - * @param numberOfEdges - to create in the graph - * @param randomizer - */ - public void createEdges( - Graph targetGraph, - Map orderToVertexMap, - int numberOfEdges, - Random randomizer); - - /** - * Checks if the graph can contain the givven numberOfEdges according to - * the graph type restrictions. For example: #V means number of - * vertexes in graph - *

    19. a Simple Graph, can have max of #V*(#V-1)/2 edges. etc - * - * @param targetGraph guranteed to start with zero edges. - * @param numberOfEdges - */ - public boolean isNumberOfEdgesValid( - Graph targetGraph, - int numberOfEdges); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Default implementation of the EdgeTopologyFactory interface. randomly - * chooses an edge and tries to add it. If the add fails from any reason - * (like: self edge / multiple edges in unpermitted graph type) it will just - * choose another and try again. Performance: - *
    20. when the number of possible edges becomes slim , this class will have - * a very poor performance , cause it will not use gready methods to choose - * them. for example : In simple graph , if #V = N (#x = number Of x) and we - * want full mesh #edges= N*(N-1)/2 , the first added edges will do so - * quickly (O(1) , the last will take O(N^2). So , do not use it in this - * kind of graphs. - *
    21. If the numberOfEdges is bigger than what the graph can add, there - * will be an infinite loop here. It is not tested. - * - * @author Assaf - * @since Aug 6, 2005 - */ - public class DefaultEdgeTopologyFactory - implements EdgeTopologyFactory - { - public void createEdges( - Graph targetGraph, - Map orderToVertexMap, - int numberOfEdges, - Random randomizer) - { - int iterationsCounter = 0; - int edgesCounter = 0; - while (edgesCounter < numberOfEdges) { - // randomizer.nextInt(int n) return a number between zero - // (inclusive) and n(exclusive) - VV startVertex = - orderToVertexMap.get( - Integer.valueOf(randomizer.nextInt(numOfVertexes))); - VV endVertex = - orderToVertexMap.get( - Integer.valueOf(randomizer.nextInt(numOfVertexes))); - try { - EE resultEdge = targetGraph.addEdge(startVertex, endVertex); - if (resultEdge != null) { - edgesCounter++; - } - } catch (Exception e) { - // do nothing.just ignore the edge - } - - iterationsCounter++; - } - } - - /** - * checks if the numOfEdges is smaller than the Max edges according to - * the following table: - * - *

      - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
      Graph TypeDirected / UnDirectedmultiple edgesloopsMax Edges
      SimpleGraphUnDirected--N(N-1)/2
      MultigraphUnDirected+-Infinite
      PseudographUnDirected++Infinite
      SimpleDirectedGraphDirected--N (N-1)
      DefaultDirectedGraphDirected-+N*(N-1)+ N = N^2
      DirectedMultigraphDirected++Infinite
      - * - * @see RandomGraphGenerator.EdgeTopologyFactory#isNumberOfEdgesValid(Graph, - * int) - */ - public boolean isNumberOfEdgesValid( - Graph targetGraph, - int numberOfEdges) - { - boolean result; - - boolean infinite = false; - int maxAllowedEdges = getMaxEdgesForVertexNum(targetGraph); - if (maxAllowedEdges == -1) { - infinite = true; - } - - if (true == infinite) { - result = true; - } else if (numberOfEdges <= maxAllowedEdges) { - result = true; - } else { - result = false; - } - return result; - } - - /** - * Return max edges for that graph. If it is infinite return -1 instead. - */ - public int getMaxEdgesForVertexNum(Graph targetGraph) - { - int maxAllowedEdges = 0; - if (targetGraph instanceof SimpleGraph) { - maxAllowedEdges = numOfVertexes * (numOfVertexes - 1) / 2; - } else if (targetGraph instanceof SimpleDirectedGraph) { - maxAllowedEdges = numOfVertexes * (numOfVertexes - 1); - } else if (targetGraph instanceof DefaultDirectedGraph) { - maxAllowedEdges = numOfVertexes * numOfVertexes; - } else { - // This may be overly liberal in the case of something - // like a simple graph which has been wrapped with - // a graph adapter or view. - maxAllowedEdges = -1; // infinite - } - return maxAllowedEdges; - } - } -} - -// End RandomGraphGenerator.java diff --git a/src/org/jgrapht/generate/RingGraphGenerator.java b/src/org/jgrapht/generate/RingGraphGenerator.java deleted file mode 100644 index 927a1b3..0000000 --- a/src/org/jgrapht/generate/RingGraphGenerator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * RingGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a ring graph of any size. A ring graph is a graph that contains a - * single cycle that passes through all its vertices exactly once. For a - * directed graph, the generated edges are oriented consistently around the - * ring. - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public class RingGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int size; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new RingGraphGenerator. - * - * @param size number of vertices to be generated - * - * @throws IllegalArgumentException if the specified size is negative. - */ - public RingGraphGenerator(int size) - { - if (size < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - this.size = size; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - if (size < 1) { - return; - } - - LinearGraphGenerator linearGenerator = - new LinearGraphGenerator(size); - Map privateMap = new HashMap(); - linearGenerator.generateGraph(target, vertexFactory, privateMap); - - V startVertex = privateMap.get(LinearGraphGenerator.START_VERTEX); - V endVertex = privateMap.get(LinearGraphGenerator.END_VERTEX); - target.addEdge(endVertex, startVertex); - } -} - -// End RingGraphGenerator.java diff --git a/src/org/jgrapht/generate/ScaleFreeGraphGenerator.java b/src/org/jgrapht/generate/ScaleFreeGraphGenerator.java deleted file mode 100644 index 18a1bed..0000000 --- a/src/org/jgrapht/generate/ScaleFreeGraphGenerator.java +++ /dev/null @@ -1,154 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * ScaleFreeGraphGenerator.java - * ----------------- - * (C) Copyright 2008-2008, by Ilya Razenshteyn and Contributors. - * - * Original Author: Ilya Razenshteyn - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates directed or undirected scale-free network - * of any size. Scale-free network is a connected graph, where degrees of - * vertices are distributed in unusual way. There are many vertices with small - * degrees and only small amount of vertices with big degrees. - * - * @author Ilya Razenshteyn - */ -public class ScaleFreeGraphGenerator - implements GraphGenerator -{ - //~ Instance fields -------------------------------------------------------- - - private int size; // size of graphs, generated by this instance of generator - private long seed; // initial seed - private Random random; // the source of randomness - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructs a new ScaleFreeGraphGenerator. - * - * @param size number of vertices to be generated - */ - public ScaleFreeGraphGenerator( - int size) - { - if (size < 0) { - throw new IllegalArgumentException( - "invalid size: " + size + " (must be non-negative)"); - } - this.size = size; - random = new Random(); - seed = random.nextLong(); - } - - /** - * Constructs a new ScaleFreeGraphGenerator using fixed - * seed for the random generator. - * - * @param size number of vertices to be generated - * @param seed initial seed for the random generator - */ - public ScaleFreeGraphGenerator( - int size, - long seed) - { - if (size < 0) { - throw new IllegalArgumentException( - "invalid size: " + size + " (must be non-negative)"); - } - this.size = size; - random = new Random(); - this.seed = seed; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Generates scale-free network with size passed to the - * constructor. Each call of this method produces identical output (but if - * target is an undirected graph, the directions of edges will be - * lost). - * - * @param target receives the generated edges and vertices; if this is - * non-empty on entry, the result will be a disconnected graph since - * generated elements will not be connected to existing elements - * @param vertexFactory called to produce new vertices - * @param resultMap unused parameter - */ - public void generateGraph( - Graph target, - VertexFactory vertexFactory, - Map resultMap) - { - random.setSeed(seed); - List vertexList = new ArrayList(); - List degrees = new ArrayList(); - int degreeSum = 0; - for (int i = 0; i < size; i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - int newDegree = 0; - while ((newDegree == 0) && (i != 0)) // we want our graph to be - // connected - - { - for (int j = 0; j < vertexList.size(); j++) { - if ((degreeSum == 0) - || (random.nextInt(degreeSum) < degrees.get(j))) - { - degrees.set(j, degrees.get(j) + 1); - newDegree++; - degreeSum += 2; - if (random.nextInt(2) == 0) { - target.addEdge(vertexList.get(j), newVertex); - } else { - target.addEdge(newVertex, vertexList.get(j)); - } - } - } - } - vertexList.add(newVertex); - degrees.add(newDegree); - } - } -} - -// End ScaleFreeGraphGenerator.java diff --git a/src/org/jgrapht/generate/StarGraphGenerator.java b/src/org/jgrapht/generate/StarGraphGenerator.java deleted file mode 100644 index b6ed2ad..0000000 --- a/src/org/jgrapht/generate/StarGraphGenerator.java +++ /dev/null @@ -1,116 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * StarGraphGenerator.java - * ------------------- - * (C) Copyright 2008-2008, by Andrew Newell and Contributors. - * - * Original Author: Andrew Newell - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 24-Dec-2008 : Initial revision (AN); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a star - * graph of any size. This is a graph where every vertex has exactly one - * edge with a center vertex. - * - * @author Andrew Newell - * @since Dec 21, 2008 - */ -public class StarGraphGenerator - implements GraphGenerator -{ - //~ Static fields/initializers --------------------------------------------- - - public static final String CENTER_VERTEX = "Center Vertex"; - - //~ Instance fields -------------------------------------------------------- - - private int order; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new StarGraphGenerator object. - * - * @param order number of total vertices including the center vertex - */ - public StarGraphGenerator(int order) - { - this.order = order; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Generates a star graph with the designated order from the constructor - */ - public void generateGraph( - Graph target, - final VertexFactory vertexFactory, - Map resultMap) - { - if (order < 1) { - return; - } - - //Create center vertex - V centerVertex = vertexFactory.createVertex(); - target.addVertex(centerVertex); - if (resultMap != null) { - resultMap.put(CENTER_VERTEX, centerVertex); - } - - //Create other vertices - for (int i = 0; i < (order - 1); i++) { - V newVertex = vertexFactory.createVertex(); - target.addVertex(newVertex); - } - - //Add one edge between the center vertex and every other vertex - Iterator iter = target.vertexSet().iterator(); - while (iter.hasNext()) { - V v = iter.next(); - if (v != centerVertex) { - target.addEdge(v, centerVertex); - } - } - } -} - -// End StarGraphGenerator.java diff --git a/src/org/jgrapht/generate/WheelGraphGenerator.java b/src/org/jgrapht/generate/WheelGraphGenerator.java deleted file mode 100644 index 2582333..0000000 --- a/src/org/jgrapht/generate/WheelGraphGenerator.java +++ /dev/null @@ -1,155 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * WheelGraphGenerator.java - * ------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * - */ -package org.jgrapht.generate; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Generates a wheel - * graph of any size. Reminding a bicycle wheel, a wheel graph has a hub - * vertex in the center and a rim of vertices around it that are connected to - * each other (as a ring). The rim vertices are also connected to the hub with - * edges that are called "spokes". - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public class WheelGraphGenerator - implements GraphGenerator -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Role for the hub vertex. - */ - public static final String HUB_VERTEX = "Hub Vertex"; - - //~ Instance fields -------------------------------------------------------- - - private boolean inwardSpokes; - private int size; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new WheelGraphGenerator object. This constructor is more - * suitable for undirected graphs, where spokes' direction is meaningless. - * In the directed case, spokes will be oriented from rim to hub. - * - * @param size number of vertices to be generated. - */ - public WheelGraphGenerator(int size) - { - this(size, true); - } - - /** - * Construct a new WheelGraphGenerator. - * - * @param size number of vertices to be generated. - * @param inwardSpokes if true and graph is directed, spokes - * are oriented from rim to hub; else from hub to rim. - * - * @throws IllegalArgumentException - */ - public WheelGraphGenerator(int size, boolean inwardSpokes) - { - if (size < 0) { - throw new IllegalArgumentException("must be non-negative"); - } - - this.size = size; - this.inwardSpokes = inwardSpokes; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * {@inheritDoc} - */ - public void generateGraph( - Graph target, - final VertexFactory vertexFactory, - Map resultMap) - { - if (size < 1) { - return; - } - - // A little trickery to intercept the rim generation. This is - // necessary since target may be initially non-empty, meaning we can't - // rely on its vertex set after the rim is generated. - final Collection rim = new ArrayList(); - VertexFactory rimVertexFactory = - new VertexFactory() { - public V createVertex() - { - V vertex = vertexFactory.createVertex(); - rim.add(vertex); - - return vertex; - } - }; - - RingGraphGenerator ringGenerator = - new RingGraphGenerator(size - 1); - ringGenerator.generateGraph(target, rimVertexFactory, resultMap); - - V hubVertex = vertexFactory.createVertex(); - target.addVertex(hubVertex); - - if (resultMap != null) { - resultMap.put(HUB_VERTEX, hubVertex); - } - - for (V rimVertex : rim) { - if (inwardSpokes) { - target.addEdge(rimVertex, hubVertex); - } else { - target.addEdge(hubVertex, rimVertex); - } - } - } -} - -// End WheelGraphGenerator.java diff --git a/src/org/jgrapht/generate/package.html b/src/org/jgrapht/generate/package.html deleted file mode 100644 index cde8047..0000000 --- a/src/org/jgrapht/generate/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Generators for graphs of various topologies. - - \ No newline at end of file diff --git a/src/org/jgrapht/graph/AbstractBaseGraph.java b/src/org/jgrapht/graph/AbstractBaseGraph.java deleted file mode 100644 index 277be87..0000000 --- a/src/org/jgrapht/graph/AbstractBaseGraph.java +++ /dev/null @@ -1,1222 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * AbstractBaseGraph.java - * ---------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): John V. Sichi - * Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 10-Aug-2003 : General edge refactoring (BN); - * 06-Nov-2003 : Change edge sharing semantics (JVS); - * 07-Feb-2004 : Enabled serialization (BN); - * 11-Mar-2004 : Made generic (CH); - * 01-Jun-2005 : Added EdgeListFactory (JVS); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * The most general implementation of the {@link org.jgrapht.Graph} interface. - * Its subclasses add various restrictions to get more specific graphs. The - * decision whether it is directed or undirected is decided at construction time - * and cannot be later modified (see constructor for details). - * - *

      This graph implementation guarantees deterministic vertex and edge set - * ordering (via {@link LinkedHashMap} and {@link LinkedHashSet}).

      - * - * @author Barak Naveh - * @since Jul 24, 2003 - */ -public abstract class AbstractBaseGraph - extends AbstractGraph - implements Graph, - Cloneable, - Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -1263088497616142427L; - - private static final String LOOPS_NOT_ALLOWED = "loops not allowed"; - - //~ Instance fields -------------------------------------------------------- - - boolean allowingLoops; - - private EdgeFactory edgeFactory; - private EdgeSetFactory edgeSetFactory; - private Map edgeMap; - private transient Set unmodifiableEdgeSet = null; - private transient Set unmodifiableVertexSet = null; - private Specifics specifics; - private boolean allowingMultipleEdges; - - private transient TypeUtil vertexTypeDecl = null; - - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new pseudograph. The pseudograph can either be directed or - * undirected, depending on the specified edge factory. - * - * @param ef the edge factory of the new graph. - * @param allowMultipleEdges whether to allow multiple edges or not. - * @param allowLoops whether to allow edges that are self-loops or not. - * - * @throws NullPointerException if the specified edge factory is - * null. - */ - public AbstractBaseGraph( - EdgeFactory ef, - boolean allowMultipleEdges, - boolean allowLoops) - { - if (ef == null) { - throw new NullPointerException(); - } - - edgeMap = new LinkedHashMap(); - edgeFactory = ef; - allowingLoops = allowLoops; - allowingMultipleEdges = allowMultipleEdges; - - specifics = createSpecifics(); - - this.edgeSetFactory = new ArrayListFactory(); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - return specifics.getAllEdges(sourceVertex, targetVertex); - } - - /** - * Returns true if and only if self-loops are allowed in this - * graph. A self loop is an edge that its source and target vertices are the - * same. - * - * @return true if and only if graph loops are allowed. - */ - public boolean isAllowingLoops() - { - return allowingLoops; - } - - /** - * Returns true if and only if multiple edges are allowed in - * this graph. The meaning of multiple edges is that there can be many edges - * going from vertex v1 to vertex v2. - * - * @return true if and only if multiple edges are allowed. - */ - public boolean isAllowingMultipleEdges() - { - return allowingMultipleEdges; - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - return specifics.getEdge(sourceVertex, targetVertex); - } - - /** - * @see Graph#getEdgeFactory() - */ - public EdgeFactory getEdgeFactory() - { - return edgeFactory; - } - - /** - * Set the {@link EdgeSetFactory} to use for this graph. Initially, a graph - * is created with a default implementation which always supplies an {@link - * java.util.ArrayList} with capacity 1. - * - * @param edgeSetFactory factory to use for subsequently created edge sets - * (this call has no effect on existing edge sets) - */ - public void setEdgeSetFactory(EdgeSetFactory edgeSetFactory) - { - this.edgeSetFactory = edgeSetFactory; - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - assertVertexExist(sourceVertex); - assertVertexExist(targetVertex); - - if (!allowingMultipleEdges - && containsEdge(sourceVertex, targetVertex)) - { - return null; - } - - if (!allowingLoops && sourceVertex.equals(targetVertex)) { - throw new IllegalArgumentException(LOOPS_NOT_ALLOWED); - } - - E e = edgeFactory.createEdge(sourceVertex, targetVertex); - - if (containsEdge(e)) { // this restriction should stay! - - return null; - } else { - IntrusiveEdge intrusiveEdge = - createIntrusiveEdge(e, sourceVertex, targetVertex); - - edgeMap.put(e, intrusiveEdge); - specifics.addEdgeToTouchingVertices(e); - - return e; - } - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - if (e == null) { - throw new NullPointerException(); - } else if (containsEdge(e)) { - return false; - } - - assertVertexExist(sourceVertex); - assertVertexExist(targetVertex); - - if (!allowingMultipleEdges - && containsEdge(sourceVertex, targetVertex)) - { - return false; - } - - if (!allowingLoops && sourceVertex.equals(targetVertex)) { - throw new IllegalArgumentException(LOOPS_NOT_ALLOWED); - } - - IntrusiveEdge intrusiveEdge = - createIntrusiveEdge(e, sourceVertex, targetVertex); - - edgeMap.put(e, intrusiveEdge); - specifics.addEdgeToTouchingVertices(e); - - return true; - } - - private IntrusiveEdge createIntrusiveEdge( - E e, - V sourceVertex, - V targetVertex) - { - IntrusiveEdge intrusiveEdge; - if (e instanceof IntrusiveEdge) { - intrusiveEdge = (IntrusiveEdge) e; - } else { - intrusiveEdge = new IntrusiveEdge(); - } - intrusiveEdge.source = sourceVertex; - intrusiveEdge.target = targetVertex; - return intrusiveEdge; - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - if (v == null) { - throw new NullPointerException(); - } else if (containsVertex(v)) { - return false; - } else { - specifics.addVertex(v); - - return true; - } - } - - /** - * @see Graph#getEdgeSource(Object) - */ - public V getEdgeSource(E e) - { - return TypeUtil.uncheckedCast( - getIntrusiveEdge(e).source, - vertexTypeDecl); - } - - /** - * @see Graph#getEdgeTarget(Object) - */ - public V getEdgeTarget(E e) - { - return TypeUtil.uncheckedCast( - getIntrusiveEdge(e).target, - vertexTypeDecl); - } - - private IntrusiveEdge getIntrusiveEdge(E e) - { - if (e instanceof IntrusiveEdge) { - return (IntrusiveEdge) e; - } - - return edgeMap.get(e); - } - - /** - * Returns a shallow copy of this graph instance. Neither edges nor vertices - * are cloned. - * - * @return a shallow copy of this set. - * - * @throws RuntimeException - * - * @see java.lang.Object#clone() - */ - public Object clone() - { - try { - TypeUtil> typeDecl = null; - - AbstractBaseGraph newGraph = - TypeUtil.uncheckedCast(super.clone(), typeDecl); - - newGraph.edgeMap = new LinkedHashMap(); - - newGraph.edgeFactory = this.edgeFactory; - newGraph.unmodifiableEdgeSet = null; - newGraph.unmodifiableVertexSet = null; - - // NOTE: it's important for this to happen in an object - // method so that the new inner class instance gets associated with - // the right outer class instance - newGraph.specifics = newGraph.createSpecifics(); - - Graphs.addGraph(newGraph, this); - - return newGraph; - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - throw new RuntimeException(); - } - } - - /** - * @see Graph#containsEdge(Object) - */ - public boolean containsEdge(E e) - { - return edgeMap.containsKey(e); - } - - /** - * @see Graph#containsVertex(Object) - */ - public boolean containsVertex(V v) - { - return specifics.getVertexSet().contains(v); - } - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - return specifics.degreeOf(vertex); - } - - /** - * @see Graph#edgeSet() - */ - public Set edgeSet() - { - if (unmodifiableEdgeSet == null) { - unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet()); - } - - return unmodifiableEdgeSet; - } - - /** - * @see Graph#edgesOf(Object) - */ - public Set edgesOf(V vertex) - { - return specifics.edgesOf(vertex); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - return specifics.inDegreeOf(vertex); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - return specifics.incomingEdgesOf(vertex); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - return specifics.outDegreeOf(vertex); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - return specifics.outgoingEdgesOf(vertex); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - E e = getEdge(sourceVertex, targetVertex); - - if (e != null) { - specifics.removeEdgeFromTouchingVertices(e); - edgeMap.remove(e); - } - - return e; - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - if (containsEdge(e)) { - specifics.removeEdgeFromTouchingVertices(e); - edgeMap.remove(e); - - return true; - } else { - return false; - } - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - if (containsVertex(v)) { - Set touchingEdgesList = edgesOf(v); - - // cannot iterate over list - will cause - // ConcurrentModificationException - removeAllEdges(new ArrayList(touchingEdgesList)); - - specifics.getVertexSet().remove(v); // remove the vertex itself - - return true; - } else { - return false; - } - } - - /** - * @see Graph#vertexSet() - */ - public Set vertexSet() - { - if (unmodifiableVertexSet == null) { - unmodifiableVertexSet = - Collections.unmodifiableSet(specifics.getVertexSet()); - } - - return unmodifiableVertexSet; - } - - /** - * @see Graph#getEdgeWeight(Object) - */ - public double getEdgeWeight(E e) - { - if (e instanceof DefaultWeightedEdge) { - return ((DefaultWeightedEdge) e).getWeight(); - } else { - return WeightedGraph.DEFAULT_EDGE_WEIGHT; - } - } - - /** - * @see WeightedGraph#setEdgeWeight(Object, double) - */ - public void setEdgeWeight(E e, double weight) - { - assert (e instanceof DefaultWeightedEdge) : e.getClass(); - ((DefaultWeightedEdge) e).weight = weight; - } - - private Specifics createSpecifics() - { - if (this instanceof DirectedGraph) { - return new DirectedSpecifics(); - } else if (this instanceof UndirectedGraph) { - return new UndirectedSpecifics(); - } else { - throw new IllegalArgumentException( - "must be instance of either DirectedGraph or UndirectedGraph"); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * . - * - * @author Barak Naveh - */ - private abstract class Specifics - implements Serializable - { - private static final long serialVersionUID = 785196247314761183L; - - public abstract void addVertex(V vertex); - - public abstract Set getVertexSet(); - - /** - * . - * - * @param sourceVertex - * @param targetVertex - * - * @return - */ - public abstract Set getAllEdges(V sourceVertex, - V targetVertex); - - /** - * . - * - * @param sourceVertex - * @param targetVertex - * - * @return - */ - public abstract E getEdge(V sourceVertex, V targetVertex); - - /** - * Adds the specified edge to the edge containers of its source and - * target vertices. - * - * @param e - */ - public abstract void addEdgeToTouchingVertices(E e); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract int degreeOf(V vertex); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract Set edgesOf(V vertex); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract int inDegreeOf(V vertex); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract Set incomingEdgesOf(V vertex); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract int outDegreeOf(V vertex); - - /** - * . - * - * @param vertex - * - * @return - */ - public abstract Set outgoingEdgesOf(V vertex); - - /** - * Removes the specified edge from the edge containers of its source and - * target vertices. - * - * @param e - */ - public abstract void removeEdgeFromTouchingVertices(E e); - } - - private static class ArrayListFactory - implements EdgeSetFactory, - Serializable - { - private static final long serialVersionUID = 5936902837403445985L; - - /** - * @see EdgeSetFactory.createEdgeSet - */ - public Set createEdgeSet(VV vertex) - { - // NOTE: use size 1 to keep memory usage under control - // for the common case of vertices with low degree - return new ArrayUnenforcedSet(1); - } - } - - /** - * A container for vertex edges. - * - *

      In this edge container we use array lists to minimize memory toll. - * However, for high-degree vertices we replace the entire edge container - * with a direct access subclass (to be implemented).

      - * - * @author Barak Naveh - */ - private static class DirectedEdgeContainer - implements Serializable - { - private static final long serialVersionUID = 7494242245729767106L; - Set incoming; - Set outgoing; - private transient Set unmodifiableIncoming = null; - private transient Set unmodifiableOutgoing = null; - - DirectedEdgeContainer(EdgeSetFactory edgeSetFactory, - VV vertex) - { - incoming = edgeSetFactory.createEdgeSet(vertex); - outgoing = edgeSetFactory.createEdgeSet(vertex); - } - - /** - * A lazy build of unmodifiable incoming edge set. - * - * @return - */ - public Set getUnmodifiableIncomingEdges() - { - if (unmodifiableIncoming == null) { - unmodifiableIncoming = Collections.unmodifiableSet(incoming); - } - - return unmodifiableIncoming; - } - - /** - * A lazy build of unmodifiable outgoing edge set. - * - * @return - */ - public Set getUnmodifiableOutgoingEdges() - { - if (unmodifiableOutgoing == null) { - unmodifiableOutgoing = Collections.unmodifiableSet(outgoing); - } - - return unmodifiableOutgoing; - } - - /** - * . - * - * @param e - */ - public void addIncomingEdge(EE e) - { - incoming.add(e); - } - - /** - * . - * - * @param e - */ - public void addOutgoingEdge(EE e) - { - outgoing.add(e); - } - - /** - * . - * - * @param e - */ - public void removeIncomingEdge(EE e) - { - incoming.remove(e); - } - - /** - * . - * - * @param e - */ - public void removeOutgoingEdge(EE e) - { - outgoing.remove(e); - } - } - - /** - * . - * - * @author Barak Naveh - */ - private class DirectedSpecifics - extends Specifics - implements Serializable - { - private static final long serialVersionUID = 8971725103718958232L; - private static final String NOT_IN_DIRECTED_GRAPH = - "no such operation in a directed graph"; - - private Map> vertexMapDirected = - new LinkedHashMap>(); - - public void addVertex(V v) - { - // add with a lazy edge container entry - vertexMapDirected.put(v, null); - } - - public Set getVertexSet() - { - return vertexMapDirected.keySet(); - } - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set edges = null; - - if (containsVertex(sourceVertex) - && containsVertex(targetVertex)) - { - edges = new ArrayUnenforcedSet(); - - DirectedEdgeContainer ec = getEdgeContainer(sourceVertex); - - Iterator iter = ec.outgoing.iterator(); - - while (iter.hasNext()) { - E e = iter.next(); - - if (getEdgeTarget(e).equals(targetVertex)) { - edges.add(e); - } - } - } - - return edges; - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - if (containsVertex(sourceVertex) - && containsVertex(targetVertex)) - { - DirectedEdgeContainer ec = getEdgeContainer(sourceVertex); - - Iterator iter = ec.outgoing.iterator(); - - while (iter.hasNext()) { - E e = iter.next(); - - if (getEdgeTarget(e).equals(targetVertex)) { - return e; - } - } - } - - return null; - } - - /** - * @see AbstractBaseGraph#addEdgeToTouchingVertices(Edge) - */ - public void addEdgeToTouchingVertices(E e) - { - V source = getEdgeSource(e); - V target = getEdgeTarget(e); - - getEdgeContainer(source).addOutgoingEdge(e); - getEdgeContainer(target).addIncomingEdge(e); - } - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - throw new UnsupportedOperationException(NOT_IN_DIRECTED_GRAPH); - } - - /** - * @see Graph#edgesOf(Object) - */ - public Set edgesOf(V vertex) - { - ArrayUnenforcedSet inAndOut = - new ArrayUnenforcedSet(getEdgeContainer(vertex).incoming); - inAndOut.addAll(getEdgeContainer(vertex).outgoing); - - // we have two copies for each self-loop - remove one of them. - if (allowingLoops) { - Set loops = getAllEdges(vertex, vertex); - - for (int i = 0; i < inAndOut.size();) { - Object e = inAndOut.get(i); - - if (loops.contains(e)) { - inAndOut.remove(i); - loops.remove(e); // so we remove it only once - } else { - i++; - } - } - } - - return Collections.unmodifiableSet(inAndOut); - } - - /** - * @see DirectedGraph#inDegree(Object) - */ - public int inDegreeOf(V vertex) - { - return getEdgeContainer(vertex).incoming.size(); - } - - /** - * @see DirectedGraph#incomingEdges(Object) - */ - public Set incomingEdgesOf(V vertex) - { - return getEdgeContainer(vertex).getUnmodifiableIncomingEdges(); - } - - /** - * @see DirectedGraph#outDegree(Object) - */ - public int outDegreeOf(V vertex) - { - return getEdgeContainer(vertex).outgoing.size(); - } - - /** - * @see DirectedGraph#outgoingEdges(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - return getEdgeContainer(vertex).getUnmodifiableOutgoingEdges(); - } - - /** - * @see AbstractBaseGraph#removeEdgeFromTouchingVertices(Edge) - */ - public void removeEdgeFromTouchingVertices(E e) - { - V source = getEdgeSource(e); - V target = getEdgeTarget(e); - - getEdgeContainer(source).removeOutgoingEdge(e); - getEdgeContainer(target).removeIncomingEdge(e); - } - - /** - * A lazy build of edge container for specified vertex. - * - * @param vertex a vertex in this graph. - * - * @return EdgeContainer - */ - private DirectedEdgeContainer getEdgeContainer(V vertex) - { - assertVertexExist(vertex); - - DirectedEdgeContainer ec = vertexMapDirected.get(vertex); - - if (ec == null) { - ec = new DirectedEdgeContainer(edgeSetFactory, vertex); - vertexMapDirected.put(vertex, ec); - } - - return ec; - } - } - - /** - * A container of for vertex edges. - * - *

      In this edge container we use array lists to minimize memory toll. - * However, for high-degree vertices we replace the entire edge container - * with a direct access subclass (to be implemented).

      - * - * @author Barak Naveh - */ - private static class UndirectedEdgeContainer - implements Serializable - { - private static final long serialVersionUID = -6623207588411170010L; - Set vertexEdges; - private transient Set unmodifiableVertexEdges = null; - - UndirectedEdgeContainer( - EdgeSetFactory edgeSetFactory, - VV vertex) - { - vertexEdges = edgeSetFactory.createEdgeSet(vertex); - } - - /** - * A lazy build of unmodifiable list of vertex edges - * - * @return - */ - public Set getUnmodifiableVertexEdges() - { - if (unmodifiableVertexEdges == null) { - unmodifiableVertexEdges = - Collections.unmodifiableSet(vertexEdges); - } - - return unmodifiableVertexEdges; - } - - /** - * . - * - * @param e - */ - public void addEdge(EE e) - { - vertexEdges.add(e); - } - - /** - * . - * - * @return - */ - public int edgeCount() - { - return vertexEdges.size(); - } - - /** - * . - * - * @param e - */ - public void removeEdge(EE e) - { - vertexEdges.remove(e); - } - } - - /** - * . - * - * @author Barak Naveh - */ - private class UndirectedSpecifics - extends Specifics - implements Serializable - { - private static final long serialVersionUID = 6494588405178655873L; - private static final String NOT_IN_UNDIRECTED_GRAPH = - "no such operation in an undirected graph"; - - private Map> vertexMapUndirected = - new LinkedHashMap>(); - - public void addVertex(V v) - { - // add with a lazy edge container entry - vertexMapUndirected.put(v, null); - } - - public Set getVertexSet() - { - return vertexMapUndirected.keySet(); - } - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set edges = null; - - if (containsVertex(sourceVertex) - && containsVertex(targetVertex)) - { - edges = new ArrayUnenforcedSet(); - - Iterator iter = - getEdgeContainer(sourceVertex).vertexEdges.iterator(); - - while (iter.hasNext()) { - E e = iter.next(); - - boolean equalStraight = - sourceVertex.equals(getEdgeSource(e)) - && targetVertex.equals(getEdgeTarget(e)); - - boolean equalInverted = - sourceVertex.equals(getEdgeTarget(e)) - && targetVertex.equals(getEdgeSource(e)); - - if (equalStraight || equalInverted) { - edges.add(e); - } - } - } - - return edges; - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - if (containsVertex(sourceVertex) - && containsVertex(targetVertex)) - { - Iterator iter = - getEdgeContainer(sourceVertex).vertexEdges.iterator(); - - while (iter.hasNext()) { - E e = iter.next(); - - boolean equalStraight = - sourceVertex.equals(getEdgeSource(e)) - && targetVertex.equals(getEdgeTarget(e)); - - boolean equalInverted = - sourceVertex.equals(getEdgeTarget(e)) - && targetVertex.equals(getEdgeSource(e)); - - if (equalStraight || equalInverted) { - return e; - } - } - } - - return null; - } - - /** - * @see AbstractBaseGraph#addEdgeToTouchingVertices(Edge) - */ - public void addEdgeToTouchingVertices(E e) - { - V source = getEdgeSource(e); - V target = getEdgeTarget(e); - - getEdgeContainer(source).addEdge(e); - - if (!source.equals(target)) { - getEdgeContainer(target).addEdge(e); - } - } - - /** - * @see UndirectedGraph#degreeOf(V) - */ - public int degreeOf(V vertex) - { - if (allowingLoops) { // then we must count, and add loops twice - - int degree = 0; - Set edges = getEdgeContainer(vertex).vertexEdges; - - for (E e : edges) { - if (getEdgeSource(e).equals(getEdgeTarget(e))) { - degree += 2; - } else { - degree += 1; - } - } - - return degree; - } else { - return getEdgeContainer(vertex).edgeCount(); - } - } - - /** - * @see Graph#edgesOf(V) - */ - public Set edgesOf(V vertex) - { - return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH); - } - - /** - * @see AbstractBaseGraph#removeEdgeFromTouchingVertices(Edge) - */ - public void removeEdgeFromTouchingVertices(E e) - { - V source = getEdgeSource(e); - V target = getEdgeTarget(e); - - getEdgeContainer(source).removeEdge(e); - - if (!source.equals(target)) { - getEdgeContainer(target).removeEdge(e); - } - } - - /** - * A lazy build of edge container for specified vertex. - * - * @param vertex a vertex in this graph. - * - * @return EdgeContainer - */ - private UndirectedEdgeContainer getEdgeContainer(V vertex) - { - assertVertexExist(vertex); - - UndirectedEdgeContainer ec = vertexMapUndirected.get(vertex); - - if (ec == null) { - ec = new UndirectedEdgeContainer( - edgeSetFactory, - vertex); - vertexMapUndirected.put(vertex, ec); - } - - return ec; - } - } -} - -// End AbstractBaseGraph.java diff --git a/src/org/jgrapht/graph/AbstractGraph.java b/src/org/jgrapht/graph/AbstractGraph.java deleted file mode 100644 index 268efcc..0000000 --- a/src/org/jgrapht/graph/AbstractGraph.java +++ /dev/null @@ -1,322 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * AbstractGraph.java - * ------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * Vladimir Kostyukov - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * 14-Jun-2012 : Added hashCode() and equals() methods implementation (VK); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * A skeletal implementation of the Graph interface, to minimize the - * effort required to implement graph interfaces. This implementation is - * applicable to both: directed graphs and undirected graphs. - * - * @author Barak Naveh - * @see Graph - * @see DirectedGraph - * @see UndirectedGraph - */ -public abstract class AbstractGraph - implements Graph -{ - //~ Constructors ----------------------------------------------------------- - - /** - * Construct a new empty graph object. - */ - public AbstractGraph() - { - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#containsEdge(Object, Object) - */ - public boolean containsEdge(V sourceVertex, V targetVertex) - { - return getEdge(sourceVertex, targetVertex) != null; - } - - /** - * @see Graph#removeAllEdges(Collection) - */ - public boolean removeAllEdges(Collection edges) - { - boolean modified = false; - - for (E e : edges) { - modified |= removeEdge(e); - } - - return modified; - } - - /** - * @see Graph#removeAllEdges(Object, Object) - */ - public Set removeAllEdges(V sourceVertex, V targetVertex) - { - Set removed = getAllEdges(sourceVertex, targetVertex); - removeAllEdges(removed); - - return removed; - } - - /** - * @see Graph#removeAllVertices(Collection) - */ - public boolean removeAllVertices(Collection vertices) - { - boolean modified = false; - - for (V v : vertices) { - modified |= removeVertex(v); - } - - return modified; - } - - /** - * Returns a string of the parenthesized pair (V, E) representing this - * G=(V,E) graph. 'V' is the string representation of the vertex set, and - * 'E' is the string representation of the edge set. - * - * @return a string representation of this graph. - */ - public String toString() - { - return toStringFromSets( - vertexSet(), - edgeSet(), - (this instanceof DirectedGraph)); - } - - /** - * Ensures that the specified vertex exists in this graph, or else throws - * exception. - * - * @param v vertex - * - * @return true if this assertion holds. - * - * @throws NullPointerException if specified vertex is null. - * @throws IllegalArgumentException if specified vertex does not exist in - * this graph. - */ - protected boolean assertVertexExist(V v) - { - if (containsVertex(v)) { - return true; - } else if (v == null) { - throw new NullPointerException(); - } else { - throw new IllegalArgumentException("no such vertex in graph"); - } - } - - /** - * Removes all the edges in this graph that are also contained in the - * specified edge array. After this call returns, this graph will contain no - * edges in common with the specified edges. This method will invoke the - * {@link Graph#removeEdge(Object)} method. - * - * @param edges edges to be removed from this graph. - * - * @return true if this graph changed as a result of the call. - * - * @see Graph#removeEdge(Object) - * @see Graph#containsEdge(Object) - */ - protected boolean removeAllEdges(E [] edges) - { - boolean modified = false; - - for (int i = 0; i < edges.length; i++) { - modified |= removeEdge(edges[i]); - } - - return modified; - } - - /** - * Helper for subclass implementations of toString( ). - * - * @param vertexSet the vertex set V to be printed - * @param edgeSet the edge set E to be printed - * @param directed true to use parens for each edge (representing directed); - * false to use curly braces (representing undirected) - * - * @return a string representation of (V,E) - */ - protected String toStringFromSets( - Collection vertexSet, - Collection edgeSet, - boolean directed) - { - List renderedEdges = new ArrayList(); - - StringBuffer sb = new StringBuffer(); - for (E e : edgeSet) { - if ((e.getClass() != DefaultEdge.class) - && (e.getClass() != DefaultWeightedEdge.class)) - { - sb.append(e.toString()); - sb.append("="); - } - if (directed) { - sb.append("("); - } else { - sb.append("{"); - } - sb.append(getEdgeSource(e)); - sb.append(","); - sb.append(getEdgeTarget(e)); - if (directed) { - sb.append(")"); - } else { - sb.append("}"); - } - - // REVIEW jvs 29-May-2006: dump weight somewhere? - renderedEdges.add(sb.toString()); - sb.setLength(0); - } - - return "(" + vertexSet + ", " + renderedEdges + ")"; - } - - /** - * Returns a hash code value for this graph. The hash code of a graph is - * defined to be the sum of the hash codes of vertices and edges in the - * graph. It is also based on graph topology and edges weights. - * - * @return the hash code value this graph - * - * @see {@link Object#equals(Object)}, {@link Object#hashCode()} - */ - public int hashCode() - { - int hash = vertexSet().hashCode(); - - for (E e: edgeSet()) { - - int part = e.hashCode(); - - int source = getEdgeSource(e).hashCode(); - int target = getEdgeTarget(e).hashCode(); - - // see http://en.wikipedia.org/wiki/Pairing_function (VK); - int pairing = ((source + target) * - (source + target + 1) / 2) + target; - part = 27 * part + pairing; - - long weight = (long) getEdgeWeight(e); - part = 27 * part + (int) (weight ^ (weight >>> 32)); - - hash += part; - } - - return hash; - } - - /** - * Indicates whether some other object is "equal to" this graph. - * Returns true if the given object is also a graph, - * the two graphs are instances of the same graph class, - * have identical vertices and edges sets with the same weights. - * - * @param obj object to be compared for equality with this graph - * - * @return true if the specified object is equal to this graph - * - * @see {@link Object#equals(Object)}, {@link Object#hashCode()} - */ - public boolean equals(Object obj) - { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - TypeUtil> typeDecl = null; - Graph g = TypeUtil.uncheckedCast(obj, typeDecl); - - if (!vertexSet().equals(g.vertexSet())) { - return false; - } - if (edgeSet().size() != g.edgeSet().size()) { - return false; - } - - for (E e: edgeSet()) { - - V source = getEdgeSource(e); - V target = getEdgeTarget(e); - - if (!g.containsEdge(e)) { - return false; - } - - if (!g.getEdgeSource(e).equals(source) - || !g.getEdgeTarget(e).equals(target)) - { - return false; - } - - if (Math.abs(getEdgeWeight(e) - g.getEdgeWeight(e)) > 10e-7) { - return false; - } - } - - return true; - } -} - -// End AbstractGraph.java diff --git a/src/org/jgrapht/graph/AsUndirectedGraph.java b/src/org/jgrapht/graph/AsUndirectedGraph.java deleted file mode 100644 index 208441b..0000000 --- a/src/org/jgrapht/graph/AsUndirectedGraph.java +++ /dev/null @@ -1,209 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * AsUndirectedGraph.java - * ---------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 14-Aug-2003 : Initial revision (JVS); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * An undirected view of the backing directed graph specified in the - * constructor. This graph allows modules to apply algorithms designed for - * undirected graphs to a directed graph by simply ignoring edge direction. If - * the backing directed graph is an oriented graph, - * then the view will be a simple graph; otherwise, it will be a multigraph. - * Query operations on this graph "read through" to the backing graph. Attempts - * to add edges will result in an UnsupportedOperationException, - * but vertex addition/removal and edge removal are all supported (and - * immediately reflected in the backing graph). - * - *

      Note that edges returned by this graph's accessors are really just the - * edges of the underlying directed graph. Since there is no interface - * distinction between directed and undirected edges, this detail should be - * irrelevant to algorithms.

      - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods. This graph will be serializable if the backing - * graph is serializable.

      - * - * @author John V. Sichi - * @since Aug 14, 2003 - */ -public class AsUndirectedGraph - extends GraphDelegator - implements Serializable, - UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3257845485078065462L; // @todo renew - private static final String NO_EDGE_ADD = - "this graph does not support edge addition"; - private static final String UNDIRECTED = - "this graph only supports undirected operations"; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for AsUndirectedGraph. - * - * @param g the backing directed graph over which an undirected view is to - * be created. - */ - public AsUndirectedGraph(DirectedGraph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set forwardList = super.getAllEdges(sourceVertex, targetVertex); - - if (sourceVertex.equals(targetVertex)) { - // avoid duplicating loops - return forwardList; - } - - Set reverseList = super.getAllEdges(targetVertex, sourceVertex); - Set list = - new ArrayUnenforcedSet( - forwardList.size() + reverseList.size()); - list.addAll(forwardList); - list.addAll(reverseList); - - return list; - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - E edge = super.getEdge(sourceVertex, targetVertex); - - if (edge != null) { - return edge; - } - - // try the other direction - return super.getEdge(targetVertex, sourceVertex); - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(NO_EDGE_ADD); - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - throw new UnsupportedOperationException(NO_EDGE_ADD); - } - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - // this counts loops twice, which is consistent with AbstractBaseGraph - return super.inDegreeOf(vertex) + super.outDegreeOf(vertex); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - throw new UnsupportedOperationException(UNDIRECTED); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - throw new UnsupportedOperationException(UNDIRECTED); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - throw new UnsupportedOperationException(UNDIRECTED); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - throw new UnsupportedOperationException(UNDIRECTED); - } - - /** - * @see AbstractBaseGraph#toString() - */ - public String toString() - { - return super.toStringFromSets(vertexSet(), edgeSet(), false); - } -} - -// End AsUndirectedGraph.java diff --git a/src/org/jgrapht/graph/AsUnweightedDirectedGraph.java b/src/org/jgrapht/graph/AsUnweightedDirectedGraph.java deleted file mode 100644 index be56777..0000000 --- a/src/org/jgrapht/graph/AsUnweightedDirectedGraph.java +++ /dev/null @@ -1,100 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * AsUnweightedGraph.java - * ---------------------- - * (C) Copyright 2007-2008, by Lucas J. Scharenbroich and Contributors. - * - * Original Author: Lucas J. Scharenbroich - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 7-Sep-2007 : Initial revision (LJS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import org.jgrapht.*; - - -/** - * An unweighted view of the backing weighted graph specified in the - * constructor. This graph allows modules to apply algorithms designed for - * unweighted graphs to a weighted graph by simply ignoring edge weights. Query - * operations on this graph "read through" to the backing graph. Vertex - * addition/removal and edge addition/removal are all supported (and immediately - * reflected in the backing graph). - * - *

      Note that edges returned by this graph's accessors are really just the - * edges of the underlying directed graph.

      - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods. This graph will be serializable if the backing - * graph is serializable.

      - * - * @author Lucas J. Scharenbroich - * @since Sep 7, 2007 - */ -public class AsUnweightedDirectedGraph - extends GraphDelegator - implements Serializable, - DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = -4320818446777715312L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for AsUnweightedGraph. - * - * @param g the backing graph over which an unweighted view is to be - * created. - */ - public AsUnweightedDirectedGraph(DirectedGraph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getEdgeWeight - */ - public double getEdgeWeight(E e) - { - return WeightedGraph.DEFAULT_EDGE_WEIGHT; - } -} - -// End AsUnweightedDirectedGraph.java diff --git a/src/org/jgrapht/graph/AsUnweightedGraph.java b/src/org/jgrapht/graph/AsUnweightedGraph.java deleted file mode 100644 index 7ee6af9..0000000 --- a/src/org/jgrapht/graph/AsUnweightedGraph.java +++ /dev/null @@ -1,100 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * AsUnweightedGraph.java - * ---------------------- - * (C) Copyright 2007-2008, by Lucas J. Scharenbroich and Contributors. - * - * Original Author: Lucas J. Scharenbroich - * Contributor(s): John V. Sichi -* - * $Id$ - * - * Changes - * ------- - * 7-Sep-2007 : Initial revision (LJS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import org.jgrapht.*; - - -/** - * An unweighted view of the backing weighted graph specified in the - * constructor. This graph allows modules to apply algorithms designed for - * unweighted graphs to a weighted graph by simply ignoring edge weights. Query - * operations on this graph "read through" to the backing graph. Vertex - * addition/removal and edge addition/removal are all supported (and immediately - * reflected in the backing graph). - * - *

      Note that edges returned by this graph's accessors are really just the - * edges of the underlying directed graph.

      - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods. This graph will be serializable if the backing - * graph is serializable.

      - * - * @author Lucas J. Scharenbroich - * @since Sep 7, 2007 - */ - -public class AsUnweightedGraph - extends GraphDelegator - implements Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = 7175505077601824663L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for AsUnweightedGraph. - * - * @param g the backing graph over which an unweighted view is to be - * created. - */ - public AsUnweightedGraph(Graph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getEdgeWeight - */ - public double getEdgeWeight(E e) - { - return WeightedGraph.DEFAULT_EDGE_WEIGHT; - } -} - -// End AsUnweightedGraph.java diff --git a/src/org/jgrapht/graph/AsWeightedGraph.java b/src/org/jgrapht/graph/AsWeightedGraph.java deleted file mode 100644 index 54fbaf1..0000000 --- a/src/org/jgrapht/graph/AsWeightedGraph.java +++ /dev/null @@ -1,147 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * AsWeightedGraph.java - * ---------------------- - * (C) Copyright 2007, by Lucas J. Scharenbroich and Contributors. - * - * Original Author: Lucas J. Scharenbroich - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 10-Sep-2007 : Initial revision (LJS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; - - -/** - *

      A weighted view of the backing graph specified in the constructor. This - * graph allows modules to apply algorithms designed for weighted graphs to an - * unweighted graph by providing an explicit edge weight mapping. The - * implementation also allows for "masking" weights for a subset of the edges in - * an existing weighted graph.

      - * - *

      Query operations on this graph "read through" to the backing graph. Vertex - * addition/removal and edge addition/removal are all supported (and immediately - * reflected in the backing graph). Setting an edge weight will pass the - * operation to the backing graph as well if the backing graph implements the - * WeightedGraph interface. Setting an edge weight will modify the weight map in - * order to maintain a consistent graph.

      - * - *

      Note that edges returned by this graph's accessors are really just the - * edges of the underlying directed graph.

      - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods. This graph will be serializable if the backing - * graph is serializable.

      - * - * @author Lucas J. Scharenbroich - * @since Sep 10, 2007 - */ -public class AsWeightedGraph - extends GraphDelegator - implements Serializable, - WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = -716810639338971372L; - - //~ Instance fields -------------------------------------------------------- - - protected final Map weightMap; - private final boolean isWeightedGraph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for AsWeightedGraph. - * - * @param g the backing graph over which a weighted view is to be created. - * @param weightMap A mapping of edges to weights. If an edge is not present - * in the weight map, the edge weight for the underlying graph is returned. - * Note that a live reference to this map is retained, so if the caller - * changes the map after construction, the changes will affect the - * AsWeightedGraph instance as well. - */ - public AsWeightedGraph(Graph g, Map weightMap) - { - super(g); - assert (weightMap != null); - this.weightMap = weightMap; - - // Remember whether the backing graph implements the WeightedGraph - // interface - this.isWeightedGraph = (g instanceof WeightedGraph); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see WeightedGraph#setEdgeWeight - */ - public void setEdgeWeight(E e, double weight) - { - if (isWeightedGraph) { - super.setEdgeWeight(e, weight); - } - - // Always modify the weight map. It would be a terrible violation - // of the use contract to silently ignore changes to the weights. - weightMap.put(e, weight); - } - - /** - * @see Graph#getEdgeWeight - */ - public double getEdgeWeight(E e) - { - double weight; - - // Always return the value from the weight map first and - // only pass the call through as a backup - if (weightMap.containsKey(e)) { - weight = weightMap.get(e); - } else { - weight = super.getEdgeWeight(e); - } - - return weight; - } -} - -// End AsWeightedGraph.java diff --git a/src/org/jgrapht/graph/ClassBasedEdgeFactory.java b/src/org/jgrapht/graph/ClassBasedEdgeFactory.java deleted file mode 100644 index 59a7dc9..0000000 --- a/src/org/jgrapht/graph/ClassBasedEdgeFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * ClassBasedEdgeFactory.java - * ------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 04-Aug-2003 : Renamed from EdgeFactoryFactory & made utility class (BN); - * 03-Nov-2003 : Made edge factories serializable (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import org.jgrapht.*; - - -/** - * An {@link EdgeFactory} for producing edges by using a class as a factory. - * - * @author Barak Naveh - * @since Jul 14, 2003 - */ -public class ClassBasedEdgeFactory - implements EdgeFactory, - Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3618135658586388792L; - - //~ Instance fields -------------------------------------------------------- - - private final Class edgeClass; - - //~ Constructors ----------------------------------------------------------- - - public ClassBasedEdgeFactory(Class edgeClass) - { - this.edgeClass = edgeClass; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see EdgeFactory#createEdge(Object, Object) - */ - public E createEdge(V source, V target) - { - try { - return edgeClass.newInstance(); - } catch (Exception ex) { - throw new RuntimeException("Edge factory failed", ex); - } - } -} - -// End ClassBasedEdgeFactory.java diff --git a/src/org/jgrapht/graph/ClassBasedVertexFactory.java b/src/org/jgrapht/graph/ClassBasedVertexFactory.java deleted file mode 100644 index 8b2e5ff..0000000 --- a/src/org/jgrapht/graph/ClassBasedVertexFactory.java +++ /dev/null @@ -1,79 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * ClassBasedVertexFactory.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A {@link VertexFactory} for producing vertices by using a class as a factory. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class ClassBasedVertexFactory - implements VertexFactory -{ - //~ Instance fields -------------------------------------------------------- - - private final Class vertexClass; - - //~ Constructors ----------------------------------------------------------- - - public ClassBasedVertexFactory(Class vertexClass) - { - this.vertexClass = vertexClass; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see VertexFactory#createVertex() - */ - public V createVertex() - { - try { - return this.vertexClass.newInstance(); - } catch (Exception e) { - throw new RuntimeException("Vertex factory failed", e); - } - } -} - -// End ClassBasedVertexFactory.java diff --git a/src/org/jgrapht/graph/DefaultDirectedGraph.java b/src/org/jgrapht/graph/DefaultDirectedGraph.java deleted file mode 100644 index 5f841a9..0000000 --- a/src/org/jgrapht/graph/DefaultDirectedGraph.java +++ /dev/null @@ -1,86 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * DefaultDirectedGraph.java - * ------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed graph. A default directed graph is a non-simple directed graph in - * which multiple edges between any two vertices are not permitted, but - * loops are. - * - *

      prefixed 'Default' to avoid name collision with the DirectedGraph - * interface.

      - */ -public class DefaultDirectedGraph - extends AbstractBaseGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3544953246956466230L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new directed graph. - * - * @param edgeClass class on which to base factory for edges - */ - public DefaultDirectedGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new directed graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public DefaultDirectedGraph(EdgeFactory ef) - { - super(ef, false, true); - } -} - -// End DefaultDirectedGraph.java diff --git a/src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java b/src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java deleted file mode 100644 index b069554..0000000 --- a/src/org/jgrapht/graph/DefaultDirectedWeightedGraph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------------------- - * DefaultDirectedWeightedGraph.java - * --------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Jun-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed weighted graph. A directed weighted graph is a non-simple directed - * graph in which multiple edges between any two vertices are not - * permitted, but loops are. The graph has weights on its edges. - * - * @see DefaultDirectedGraph - */ -public class DefaultDirectedWeightedGraph - extends DefaultDirectedGraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3761405317841171513L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new directed weighted graph. - * - * @param edgeClass class on which to base factory for edges - */ - public DefaultDirectedWeightedGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new directed weighted graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public DefaultDirectedWeightedGraph(EdgeFactory ef) - { - super(ef); - } -} - -// End DefaultDirectedWeightedGraph.java diff --git a/src/org/jgrapht/graph/DefaultEdge.java b/src/org/jgrapht/graph/DefaultEdge.java deleted file mode 100644 index 1d7422c..0000000 --- a/src/org/jgrapht/graph/DefaultEdge.java +++ /dev/null @@ -1,91 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * DefaultEdge.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 10-Aug-2003 : General edge refactoring (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A default implementation for edges in a {@link Graph}. - * - * @author Barak Naveh - * @since Jul 14, 2003 - */ -public class DefaultEdge - extends IntrusiveEdge -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3258408452177932855L; - - //~ Methods ---------------------------------------------------------------- - - /** - * Retrieves the source of this edge. This is protected, for use by - * subclasses only (e.g. for implementing toString). - * - * @return source of this edge - */ - protected Object getSource() - { - return source; - } - - /** - * Retrieves the target of this edge. This is protected, for use by - * subclasses only (e.g. for implementing toString). - * - * @return target of this edge - */ - protected Object getTarget() - { - return target; - } - - public String toString() - { - return "(" + source + " : " + target + ")"; - } -} - -// End DefaultEdge.java diff --git a/src/org/jgrapht/graph/DefaultGraphMapping.java b/src/org/jgrapht/graph/DefaultGraphMapping.java deleted file mode 100644 index 8738906..0000000 --- a/src/org/jgrapht/graph/DefaultGraphMapping.java +++ /dev/null @@ -1,135 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * DefaultGraphMapping.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Implementation of the GraphMapping interface. The performance of - * getVertex/EdgeCorrespondence is based on the performance of the - * concrete Map class which is passed in the constructor. For example, using - * hashmaps will provide O(1) performence. - * - * @author Assaf - * @since Jul 30, 2005 - */ -public class DefaultGraphMapping - implements GraphMapping -{ - //~ Instance fields -------------------------------------------------------- - - private Map graphMappingForward; - private Map graphMappingReverse; - - private Graph graph1; - private Graph graph2; - - //~ Constructors ----------------------------------------------------------- - - /** - * The maps themselves are used. There is no defensive-copy. Assumption: The - * key and value in the mappings are of valid graph objects. It is not - * checked. - * - * @param g1ToG2 - * @param g2ToG1 - * @param g1 - * @param g2 - */ - public DefaultGraphMapping( - Map g1ToG2, - Map g2ToG1, - Graph g1, - Graph g2) - { - this.graph1 = g1; - this.graph2 = g2; - this.graphMappingForward = g1ToG2; - this.graphMappingReverse = g2ToG1; - } - - //~ Methods ---------------------------------------------------------------- - - public E getEdgeCorrespondence(E currEdge, boolean forward) - { - Graph sourceGraph, targetGraph; - - if (forward) { - sourceGraph = this.graph1; - targetGraph = this.graph2; - } else { - sourceGraph = this.graph2; - targetGraph = this.graph1; - } - - V mappedSourceVertex = - getVertexCorrespondence( - sourceGraph.getEdgeSource(currEdge), - forward); - V mappedTargetVertex = - getVertexCorrespondence( - sourceGraph.getEdgeTarget(currEdge), - forward); - if ((mappedSourceVertex == null) || (mappedTargetVertex == null)) { - return null; - } else { - return targetGraph.getEdge( - mappedSourceVertex, - mappedTargetVertex); - } - } - - public V getVertexCorrespondence( - V keyVertex, - boolean forward) - { - Map graphMapping; - if (forward) { - graphMapping = graphMappingForward; - } else { - graphMapping = graphMappingReverse; - } - - return graphMapping.get(keyVertex); - } -} - -// End DefaultGraphMapping.java diff --git a/src/org/jgrapht/graph/DefaultListenableGraph.java b/src/org/jgrapht/graph/DefaultListenableGraph.java deleted file mode 100644 index d131732..0000000 --- a/src/org/jgrapht/graph/DefaultListenableGraph.java +++ /dev/null @@ -1,524 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------------- - * DefaultListenableGraph.java - * --------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 04-Aug-2003 : Strong refs to listeners instead of weak refs (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 07-Mar-2004 : Fixed unnecessary clone bug #819075 (BN); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; -import org.jgrapht.util.*; - - -/** - * A graph backed by the the graph specified at the constructor, which can be - * listened by GraphListener s and by - * VertexSetListener s. Operations on this graph "pass through" to the to - * the backing graph. Any modification made to this graph or the backing graph - * is reflected by the other. - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods.

      - * - * @author Barak Naveh - * @see GraphListener - * @see VertexSetListener - * @since Jul 20, 2003 - */ -public class DefaultListenableGraph - extends GraphDelegator - implements ListenableGraph, - Cloneable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3977575900898471984L; - - //~ Instance fields -------------------------------------------------------- - - private List> graphListeners = - new ArrayList>(); - private List> vertexSetListeners = - new ArrayList>(); - private FlyweightEdgeEvent reuseableEdgeEvent; - private FlyweightVertexEvent reuseableVertexEvent; - private boolean reuseEvents; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new listenable graph. - * - * @param g the backing graph. - */ - public DefaultListenableGraph(Graph g) - { - this(g, false); - } - - /** - * Creates a new listenable graph. If the reuseEvents flag is - * set to true this class will reuse previously fired events - * and will not create a new object for each event. This option increases - * performance but should be used with care, especially in multithreaded - * environment. - * - * @param g the backing graph. - * @param reuseEvents whether to reuse previously fired event objects - * instead of creating a new event object for each event. - * - * @throws IllegalArgumentException if the backing graph is already a - * listenable graph. - */ - public DefaultListenableGraph(Graph g, boolean reuseEvents) - { - super(g); - this.reuseEvents = reuseEvents; - reuseableEdgeEvent = new FlyweightEdgeEvent(this, -1, null); - reuseableVertexEvent = new FlyweightVertexEvent(this, -1, null); - - // the following restriction could be probably relaxed in the future. - if (g instanceof ListenableGraph) { - throw new IllegalArgumentException( - "base graph cannot be listenable"); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * If the reuseEvents flag is set to true this - * class will reuse previously fired events and will not create a new object - * for each event. This option increases performance but should be used with - * care, especially in multithreaded environment. - * - * @param reuseEvents whether to reuse previously fired event objects - * instead of creating a new event object for each event. - */ - public void setReuseEvents(boolean reuseEvents) - { - this.reuseEvents = reuseEvents; - } - - /** - * Tests whether the reuseEvents flag is set. If the flag is - * set to true this class will reuse previously fired events - * and will not create a new object for each event. This option increases - * performance but should be used with care, especially in multithreaded - * environment. - * - * @return the value of the reuseEvents flag. - */ - public boolean isReuseEvents() - { - return reuseEvents; - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - E e = super.addEdge(sourceVertex, targetVertex); - - if (e != null) { - fireEdgeAdded(e, sourceVertex, targetVertex); - } - - return e; - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - boolean added = super.addEdge(sourceVertex, targetVertex, e); - - if (added) { - fireEdgeAdded(e, sourceVertex, targetVertex); - } - - return added; - } - - /** - * @see ListenableGraph#addGraphListener(GraphListener) - */ - public void addGraphListener(GraphListener l) - { - addToListenerList(graphListeners, l); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - boolean modified = super.addVertex(v); - - if (modified) { - fireVertexAdded(v); - } - - return modified; - } - - /** - * @see ListenableGraph#addVertexSetListener(VertexSetListener) - */ - public void addVertexSetListener(VertexSetListener l) - { - addToListenerList(vertexSetListeners, l); - } - - /** - * @see java.lang.Object#clone() - */ - public Object clone() - { - try { - TypeUtil> typeDecl = null; - - DefaultListenableGraph g = - TypeUtil.uncheckedCast(super.clone(), typeDecl); - g.graphListeners = new ArrayList>(); - g.vertexSetListeners = new ArrayList>(); - - return g; - } catch (CloneNotSupportedException e) { - // should never get here since we're Cloneable - e.printStackTrace(); - throw new RuntimeException("internal error"); - } - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - E e = super.removeEdge(sourceVertex, targetVertex); - - if (e != null) { - fireEdgeRemoved(e, sourceVertex, targetVertex); - } - - return e; - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - V sourceVertex = getEdgeSource(e); - V targetVertex = getEdgeTarget(e); - - boolean modified = super.removeEdge(e); - - if (modified) { - fireEdgeRemoved(e, sourceVertex, targetVertex); - } - - return modified; - } - - /** - * @see ListenableGraph#removeGraphListener(GraphListener) - */ - public void removeGraphListener(GraphListener l) - { - graphListeners.remove(l); - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - if (containsVertex(v)) { - Set touchingEdgesList = edgesOf(v); - - // copy set to avoid ConcurrentModificationException - removeAllEdges(new ArrayList(touchingEdgesList)); - - super.removeVertex(v); // remove the vertex itself - - fireVertexRemoved(v); - - return true; - } else { - return false; - } - } - - /** - * @see ListenableGraph#removeVertexSetListener(VertexSetListener) - */ - public void removeVertexSetListener(VertexSetListener l) - { - vertexSetListeners.remove(l); - } - - /** - * Notify listeners that the specified edge was added. - * - * @param edge the edge that was added. - * - * @param source edge source - * - * @param target edge target - */ - protected void fireEdgeAdded(E edge, V source, V target) - { - GraphEdgeChangeEvent e = - createGraphEdgeChangeEvent( - GraphEdgeChangeEvent.EDGE_ADDED, - edge, source, target); - - for (GraphListener l : graphListeners) { - l.edgeAdded(e); - } - } - - /** - * Notify listeners that the specified edge was removed. - * - * @param edge the edge that was removed. - * - * @param source edge source - * - * @param target edge target - */ - protected void fireEdgeRemoved(E edge, V source, V target) - { - GraphEdgeChangeEvent e = - createGraphEdgeChangeEvent( - GraphEdgeChangeEvent.EDGE_REMOVED, - edge, source, target); - - for (GraphListener l : graphListeners) { - l.edgeRemoved(e); - } - } - - /** - * Notify listeners that the specified vertex was added. - * - * @param vertex the vertex that was added. - */ - protected void fireVertexAdded(V vertex) - { - GraphVertexChangeEvent e = - createGraphVertexChangeEvent( - GraphVertexChangeEvent.VERTEX_ADDED, - vertex); - - for (VertexSetListener l : vertexSetListeners) { - l.vertexAdded(e); - } - - for (GraphListener l : graphListeners) { - l.vertexAdded(e); - } - } - - /** - * Notify listeners that the specified vertex was removed. - * - * @param vertex the vertex that was removed. - */ - protected void fireVertexRemoved(V vertex) - { - GraphVertexChangeEvent e = - createGraphVertexChangeEvent( - GraphVertexChangeEvent.VERTEX_REMOVED, - vertex); - - for (VertexSetListener l : vertexSetListeners) { - l.vertexRemoved(e); - } - - for (GraphListener l : graphListeners) { - l.vertexRemoved(e); - } - } - - private static void addToListenerList( - List list, - L l) - { - if (!list.contains(l)) { - list.add(l); - } - } - - private GraphEdgeChangeEvent createGraphEdgeChangeEvent( - int eventType, E edge, V source, V target) - { - if (reuseEvents) { - reuseableEdgeEvent.setType(eventType); - reuseableEdgeEvent.setEdge(edge); - reuseableEdgeEvent.setEdgeSource(source); - reuseableEdgeEvent.setEdgeTarget(target); - - return reuseableEdgeEvent; - } else { - return new GraphEdgeChangeEvent( - this, eventType, edge, source, target); - } - } - - private GraphVertexChangeEvent createGraphVertexChangeEvent( - int eventType, - V vertex) - { - if (reuseEvents) { - reuseableVertexEvent.setType(eventType); - reuseableVertexEvent.setVertex(vertex); - - return reuseableVertexEvent; - } else { - return new GraphVertexChangeEvent(this, eventType, vertex); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * A reuseable edge event. - * - * @author Barak Naveh - * @since Aug 10, 2003 - */ - private static class FlyweightEdgeEvent - extends GraphEdgeChangeEvent - { - private static final long serialVersionUID = 3907207152526636089L; - - /** - * @see GraphEdgeChangeEvent#GraphEdgeChangeEvent(Object, int, Edge) - */ - public FlyweightEdgeEvent(Object eventSource, int type, EE e) - { - super(eventSource, type, e); - } - - /** - * Sets the edge of this event. - * - * @param e the edge to be set. - */ - protected void setEdge(EE e) - { - this.edge = e; - } - - protected void setEdgeSource(VV v) - { - this.edgeSource = v; - } - - protected void setEdgeTarget(VV v) - { - this.edgeTarget = v; - } - - /** - * Set the event type of this event. - * - * @param type the type to be set. - */ - protected void setType(int type) - { - this.type = type; - } - } - - /** - * A reuseable vertex event. - * - * @author Barak Naveh - * @since Aug 10, 2003 - */ - private static class FlyweightVertexEvent - extends GraphVertexChangeEvent - { - private static final long serialVersionUID = 3257848787857585716L; - - /** - * @see GraphVertexChangeEvent#GraphVertexChangeEvent(Object, int, - * Object) - */ - public FlyweightVertexEvent(Object eventSource, int type, VV vertex) - { - super(eventSource, type, vertex); - } - - /** - * Set the event type of this event. - * - * @param type type to be set. - */ - protected void setType(int type) - { - this.type = type; - } - - /** - * Sets the vertex of this event. - * - * @param vertex the vertex to be set. - */ - protected void setVertex(VV vertex) - { - this.vertex = vertex; - } - } -} - -// End DefaultListenableGraph.java diff --git a/src/org/jgrapht/graph/DefaultWeightedEdge.java b/src/org/jgrapht/graph/DefaultWeightedEdge.java deleted file mode 100644 index 172fe9d..0000000 --- a/src/org/jgrapht/graph/DefaultWeightedEdge.java +++ /dev/null @@ -1,77 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * DefaultWeightedEdge.java - * ---------------- - * (C) Copyright 2006-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 29-May-2006 : Initial revision (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A default implementation for edges in a {@link WeightedGraph}. All access to - * the weight of an edge must go through the graph interface, which is why this - * class doesn't expose any public methods. - * - * @author John V. Sichi - */ -public class DefaultWeightedEdge - extends DefaultEdge -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 229708706467350994L; - - //~ Instance fields -------------------------------------------------------- - - double weight = WeightedGraph.DEFAULT_EDGE_WEIGHT; - - //~ Methods ---------------------------------------------------------------- - - /** - * Retrieves the weight of this edge. This is protected, for use by - * subclasses only (e.g. for implementing toString). - * - * @return weight of this edge - */ - protected double getWeight() - { - return weight; - } -} - -// End DefaultWeightedEdge.java diff --git a/src/org/jgrapht/graph/DirectedGraphUnion.java b/src/org/jgrapht/graph/DirectedGraphUnion.java deleted file mode 100644 index b151370..0000000 --- a/src/org/jgrapht/graph/DirectedGraphUnion.java +++ /dev/null @@ -1,109 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * DirectedGraphUnion.java - * ------------------------- - * (C) Copyright 2009-2009, by Ilya Razenshteyn - * - * Original Author: Ilya Razenshteyn and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 02-Feb-2009 : Initial revision (IR); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -public class DirectedGraphUnion - extends GraphUnion> - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -740199233080172450L; - - //~ Constructors ----------------------------------------------------------- - - public DirectedGraphUnion( - DirectedGraph g1, - DirectedGraph g2, - WeightCombiner operator) - { - super(g1, g2, operator); - } - - public DirectedGraphUnion(DirectedGraph g1, DirectedGraph g2) - { - super(g1, g2); - } - - //~ Methods ---------------------------------------------------------------- - - public int inDegreeOf(V vertex) - { - Set res = incomingEdgesOf(vertex); - return res.size(); - } - - public Set incomingEdgesOf(V vertex) - { - Set res = new HashSet(); - if (getG1().containsVertex(vertex)) { - res.addAll(getG1().incomingEdgesOf(vertex)); - } - if (getG2().containsVertex(vertex)) { - res.addAll(getG2().incomingEdgesOf(vertex)); - } - return Collections.unmodifiableSet(res); - } - - public int outDegreeOf(V vertex) - { - Set res = outgoingEdgesOf(vertex); - return res.size(); - } - - public Set outgoingEdgesOf(V vertex) - { - Set res = new HashSet(); - if (getG1().containsVertex(vertex)) { - res.addAll(getG1().outgoingEdgesOf(vertex)); - } - if (getG2().containsVertex(vertex)) { - res.addAll(getG2().outgoingEdgesOf(vertex)); - } - return Collections.unmodifiableSet(res); - } -} - -// End DirectedGraphUnion.java diff --git a/src/org/jgrapht/graph/DirectedMaskSubgraph.java b/src/org/jgrapht/graph/DirectedMaskSubgraph.java deleted file mode 100644 index fdeaf32..0000000 --- a/src/org/jgrapht/graph/DirectedMaskSubgraph.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * DirectedMaskSubgraph.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed graph that is a {@link MaskSubgraph} on another graph. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class DirectedMaskSubgraph - extends MaskSubgraph - implements DirectedGraph -{ - //~ Constructors ----------------------------------------------------------- - - public DirectedMaskSubgraph( - DirectedGraph base, - MaskFunctor mask) - { - super(base, mask); - } -} - -// End DirectedMaskSubgraph.java diff --git a/src/org/jgrapht/graph/DirectedMultigraph.java b/src/org/jgrapht/graph/DirectedMultigraph.java deleted file mode 100644 index 869674f..0000000 --- a/src/org/jgrapht/graph/DirectedMultigraph.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------- - * DirectedMultigraph.java - * ----------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed multigraph. A directed multigraph is a non-simple directed graph - * in which loops and multiple edges between any two vertices are permitted. - */ -public class DirectedMultigraph - extends AbstractBaseGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3258408413590599219L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new directed multigraph. - * - * @param edgeClass class on which to base factory for edges - */ - public DirectedMultigraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new directed multigraph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public DirectedMultigraph(EdgeFactory ef) - { - super(ef, true, true); - } -} - -// End DirectedMultigraph.java diff --git a/src/org/jgrapht/graph/DirectedPseudograph.java b/src/org/jgrapht/graph/DirectedPseudograph.java deleted file mode 100644 index 6cf0be5..0000000 --- a/src/org/jgrapht/graph/DirectedPseudograph.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * DirectedPseudograph.java - * ---------------- - * (C) Copyright 2004-2008, by Christian Hammer and Contributors. - * - * Original Author: Christian Hammer - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 11-Mar-2004 : Initial revision: generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed pseudograph. A directed pseudograph is a non-simple directed graph - * in which both graph loops and multiple edges are permitted. If you're unsure - * about pseudographs, see: - * http://mathworld.wolfram.com/Pseudograph.html. - */ -public class DirectedPseudograph - extends AbstractBaseGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -8300409752893486415L; - - //~ Constructors ----------------------------------------------------------- - - /** - * @see AbstractBaseGraph - */ - public DirectedPseudograph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * @see AbstractBaseGraph - */ - public DirectedPseudograph(EdgeFactory ef) - { - super(ef, true, true); - } -} - -// End DirectedPseudograph.java diff --git a/src/org/jgrapht/graph/DirectedSubgraph.java b/src/org/jgrapht/graph/DirectedSubgraph.java deleted file mode 100644 index 5161135..0000000 --- a/src/org/jgrapht/graph/DirectedSubgraph.java +++ /dev/null @@ -1,158 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------- - * DirectedSubgraph.java - * --------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * A directed graph that is a subgraph on other graph. - * - * @see Subgraph - */ -public class DirectedSubgraph - extends Subgraph> - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3616445700507054133L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new directed subgraph. - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - * @param edgeSubset edges to in include in the subgraph. If - * null then all the edges whose vertices found in the graph - * are included. - */ - public DirectedSubgraph( - DirectedGraph base, - Set vertexSubset, - Set edgeSubset) - { - super(base, vertexSubset, edgeSubset); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - assertVertexExist(vertex); - - int degree = 0; - - for (E e : getBase().incomingEdgesOf(vertex)) { - if (containsEdge(e)) { - degree++; - } - } - - return degree; - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - assertVertexExist(vertex); - - Set edges = new ArrayUnenforcedSet(); - - for (E e : getBase().incomingEdgesOf(vertex)) { - if (containsEdge(e)) { - edges.add(e); - } - } - - return edges; - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - assertVertexExist(vertex); - - int degree = 0; - - for (E e : getBase().outgoingEdgesOf(vertex)) { - if (containsEdge(e)) { - degree++; - } - } - - return degree; - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - assertVertexExist(vertex); - - Set edges = new ArrayUnenforcedSet(); - - for (E e : getBase().outgoingEdgesOf(vertex)) { - if (containsEdge(e)) { - edges.add(e); - } - } - - return edges; - } -} - -// End DirectedSubgraph.java diff --git a/src/org/jgrapht/graph/DirectedWeightedMultigraph.java b/src/org/jgrapht/graph/DirectedWeightedMultigraph.java deleted file mode 100644 index 06484ab..0000000 --- a/src/org/jgrapht/graph/DirectedWeightedMultigraph.java +++ /dev/null @@ -1,84 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------- - * DirectedWeightedMultigraph.java - * ------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Jun-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed weighted multigraph. A directed weighted multigraph is a - * non-simple directed graph in which loops and multiple edges between any two - * vertices are permitted, and edges have weights. - */ -public class DirectedWeightedMultigraph - extends DirectedMultigraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 4049071636005206066L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new directed weighted multigraph. - * - * @param edgeClass class on which to base factory for edges - */ - public DirectedWeightedMultigraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new directed weighted multigraph with the specified edge - * factory. - * - * @param ef the edge factory of the new graph. - */ - public DirectedWeightedMultigraph(EdgeFactory ef) - { - super(ef); - } -} - -// End DirectedWeightedMultigraph.java diff --git a/src/org/jgrapht/graph/DirectedWeightedSubgraph.java b/src/org/jgrapht/graph/DirectedWeightedSubgraph.java deleted file mode 100644 index 8e852d5..0000000 --- a/src/org/jgrapht/graph/DirectedWeightedSubgraph.java +++ /dev/null @@ -1,83 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------------- - * DirectedWeightedSubgraph.java - * ----------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * A directed weighted graph that is a subgraph on other graph. - * - * @see Subgraph - */ -public class DirectedWeightedSubgraph - extends DirectedSubgraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3905799799168250680L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new weighted directed subgraph. - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - * @param edgeSubset edges to in include in the subgraph. If - * null then all the edges whose vertices found in the graph - * are included. - */ - public DirectedWeightedSubgraph( - WeightedGraph base, - Set vertexSubset, - Set edgeSubset) - { - super((DirectedGraph) base, vertexSubset, edgeSubset); - } -} - -// End DirectedWeightedSubgraph.java diff --git a/src/org/jgrapht/graph/EdgeReversedGraph.java b/src/org/jgrapht/graph/EdgeReversedGraph.java deleted file mode 100644 index ab21b56..0000000 --- a/src/org/jgrapht/graph/EdgeReversedGraph.java +++ /dev/null @@ -1,187 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------- - * EdgeReversedGraph.java - * ------------- - * (C) Copyright 2006-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 16-Sept-2006 : Initial revision (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Provides an edge-reversed view g' of a directed graph g. The vertex sets for - * the two graphs are the same, but g' contains an edge (v2, v1) iff g contains - * an edge (v1, v2). g' is backed by g, so changes to g are reflected in g', and - * vice versa. - * - *

      This class allows you to use a directed graph algorithm in reverse. For - * example, suppose you have a directed graph representing a tree, with edges - * from parent to child, and you want to find all of the parents of a node. To - * do this, simply create an edge-reversed graph and pass that as input to - * {@link org.jgrapht.traverse.DepthFirstIterator}. - * - * @author John V. Sichi - * @see AsUndirectedGraph - */ -public class EdgeReversedGraph - extends GraphDelegator - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = 9091361782455418631L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new EdgeReversedGraph. - * - * @param g the base (backing) graph on which the edge-reversed view will be - * based. - */ - public EdgeReversedGraph(DirectedGraph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - return super.getEdge(targetVertex, sourceVertex); - } - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - return super.getAllEdges(targetVertex, sourceVertex); - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - return super.addEdge(targetVertex, sourceVertex); - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - return super.addEdge(targetVertex, sourceVertex, e); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - return super.outDegreeOf(vertex); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - return super.inDegreeOf(vertex); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - return super.outgoingEdgesOf(vertex); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - return super.incomingEdgesOf(vertex); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - return super.removeEdge(targetVertex, sourceVertex); - } - - /** - * @see Graph#getEdgeSource(Object) - */ - public V getEdgeSource(E e) - { - return super.getEdgeTarget(e); - } - - /** - * @see Graph#getEdgeTarget(Object) - */ - public V getEdgeTarget(E e) - { - return super.getEdgeSource(e); - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() - { - return toStringFromSets( - vertexSet(), - edgeSet(), - true); - } -} - -// End EdgeReversedGraph.java diff --git a/src/org/jgrapht/graph/EdgeSetFactory.java b/src/org/jgrapht/graph/EdgeSetFactory.java deleted file mode 100644 index 828659c..0000000 --- a/src/org/jgrapht/graph/EdgeSetFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * EdgeSetFactory.java - * ---------------- - * (C) Copyright 2005-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 01-Jun-2005 : Initial revision (JVS); - * 06-Aug-2005 : Made generic (CH); - * 07-May-2006 : Renamed and changed from List to Set (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - - -/** - * A factory for edge sets. This interface allows the creator of a graph to - * choose the {@link java.util.Set} implementation used internally by the graph - * to maintain sets of edges. This provides control over performance tradeoffs - * between memory and CPU usage. - * - * @author John V. Sichi - */ -public interface EdgeSetFactory -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Create a new edge set for a particular vertex. - * - * @param vertex the vertex for which the edge set is being created; - * sophisticated factories may be able to use this information to choose an - * optimal set representation (e.g. ArrayUnenforcedSet for a vertex expected - * to have low degree, and LinkedHashSet for a vertex expected to have high - * degree) - * - * @return new set - */ - public Set createEdgeSet(V vertex); -} - -// End EdgeSetFactory.java diff --git a/src/org/jgrapht/graph/GraphDelegator.java b/src/org/jgrapht/graph/GraphDelegator.java deleted file mode 100644 index 1f4e6dc..0000000 --- a/src/org/jgrapht/graph/GraphDelegator.java +++ /dev/null @@ -1,298 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * GraphDelegator.java - * ------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * A graph backed by the the graph specified at the constructor, which delegates - * all its methods to the backing graph. Operations on this graph "pass through" - * to the to the backing graph. Any modification made to this graph or the - * backing graph is reflected by the other. - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods.

      - * - *

      This class is mostly used as a base for extending subclasses.

      - * - * @author Barak Naveh - * @since Jul 20, 2003 - */ -public class GraphDelegator - extends AbstractGraph - implements Graph, - Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3257005445226181425L; - - //~ Instance fields -------------------------------------------------------- - - /** - * The graph to which operations are delegated. - */ - private Graph delegate; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructor for GraphDelegator. - * - * @param g the backing graph (the delegate). - * - * @throws IllegalArgumentException iff g==null - */ - public GraphDelegator(Graph g) - { - super(); - - if (g == null) { - throw new IllegalArgumentException("g must not be null."); - } - - delegate = g; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - return delegate.getAllEdges(sourceVertex, targetVertex); - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - return delegate.getEdge(sourceVertex, targetVertex); - } - - /** - * @see Graph#getEdgeFactory() - */ - public EdgeFactory getEdgeFactory() - { - return delegate.getEdgeFactory(); - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - return delegate.addEdge(sourceVertex, targetVertex); - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - return delegate.addEdge(sourceVertex, targetVertex, e); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - return delegate.addVertex(v); - } - - /** - * @see Graph#containsEdge(Object) - */ - public boolean containsEdge(E e) - { - return delegate.containsEdge(e); - } - - /** - * @see Graph#containsVertex(Object) - */ - public boolean containsVertex(V v) - { - return delegate.containsVertex(v); - } - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - return ((UndirectedGraph) delegate).degreeOf(vertex); - } - - /** - * @see Graph#edgeSet() - */ - public Set edgeSet() - { - return delegate.edgeSet(); - } - - /** - * @see Graph#edgesOf(Object) - */ - public Set edgesOf(V vertex) - { - return delegate.edgesOf(vertex); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - return ((DirectedGraph) delegate).inDegreeOf(vertex); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - return ((DirectedGraph) delegate).incomingEdgesOf(vertex); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - return ((DirectedGraph) delegate).outDegreeOf(vertex); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - return ((DirectedGraph) delegate).outgoingEdgesOf(vertex); - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - return delegate.removeEdge(e); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - return delegate.removeEdge(sourceVertex, targetVertex); - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - return delegate.removeVertex(v); - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() - { - return delegate.toString(); - } - - /** - * @see Graph#vertexSet() - */ - public Set vertexSet() - { - return delegate.vertexSet(); - } - - /** - * @see Graph#getEdgeSource(Object) - */ - public V getEdgeSource(E e) - { - return delegate.getEdgeSource(e); - } - - /** - * @see Graph#getEdgeTarget(Object) - */ - public V getEdgeTarget(E e) - { - return delegate.getEdgeTarget(e); - } - - /** - * @see Graph#getEdgeWeight(Object) - */ - public double getEdgeWeight(E e) - { - return delegate.getEdgeWeight(e); - } - - /** - * @see WeightedGraph#setEdgeWeight(Object, double) - */ - public void setEdgeWeight(E e, double weight) - { - ((WeightedGraph) delegate).setEdgeWeight(e, weight); - } -} - -// End GraphDelegator.java diff --git a/src/org/jgrapht/graph/GraphPathImpl.java b/src/org/jgrapht/graph/GraphPathImpl.java deleted file mode 100644 index b2e3b91..0000000 --- a/src/org/jgrapht/graph/GraphPathImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * GraphPathImpl.java - * ---------------- - * (C) Copyright 2009-2009, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 03-Jul-2009 : Initial revision (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * GraphPathImpl is a default implementation of {@link GraphPath}. - * - * @author John Sichi - * @version $Id$ - */ -public class GraphPathImpl - implements GraphPath -{ - //~ Instance fields -------------------------------------------------------- - - private Graph graph; - - private List edgeList; - - private V startVertex; - - private V endVertex; - - private double weight; - - //~ Constructors ----------------------------------------------------------- - - public GraphPathImpl( - Graph graph, - V startVertex, - V endVertex, - List edgeList, - double weight) - { - this.graph = graph; - this.startVertex = startVertex; - this.endVertex = endVertex; - this.edgeList = edgeList; - this.weight = weight; - } - - //~ Methods ---------------------------------------------------------------- - - // implement GraphPath - public Graph getGraph() - { - return graph; - } - - // implement GraphPath - public V getStartVertex() - { - return startVertex; - } - - // implement GraphPath - public V getEndVertex() - { - return endVertex; - } - - // implement GraphPath - public List getEdgeList() - { - return edgeList; - } - - // implement GraphPath - public double getWeight() - { - return weight; - } - - // override Object - public String toString() - { - return edgeList.toString(); - } -} - -// End GraphPathImpl.java diff --git a/src/org/jgrapht/graph/GraphUnion.java b/src/org/jgrapht/graph/GraphUnion.java deleted file mode 100644 index 6659c07..0000000 --- a/src/org/jgrapht/graph/GraphUnion.java +++ /dev/null @@ -1,288 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * GraphUnion.java - * ------------------------- - * (C) Copyright 2009-2009, by Ilya Razenshteyn - * - * Original Author: Ilya Razenshteyn and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 02-Feb-2009 : Initial revision (IR); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - *

      Read-only union of two graphs: G1 and G2. If - * G1 = (V1, E1) and G2 = - * (V2, E2) then their union G = (V, E), where V is the - * union of V1 and V2, and E is the union of E1 - * and E1.

      - * - *

      GraphUnion implements Graph interface. - * GraphUnion uses WeightCombiner to choose policy for calculating - * edge weight.

      - */ -public class GraphUnion> - extends AbstractGraph - implements Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -740199233080172450L; - - private static final String READ_ONLY = "union of graphs is read-only"; - - //~ Instance fields -------------------------------------------------------- - - private G g1; - private G g2; - private WeightCombiner operator; - - //~ Constructors ----------------------------------------------------------- - - public GraphUnion(G g1, G g2, WeightCombiner operator) - { - if (g1 == null) { - throw new NullPointerException("g1 is null"); - } - if (g2 == null) { - throw new NullPointerException("g2 is null"); - } - if (g1 == g2) { - throw new IllegalArgumentException("g1 is equal to g2"); - } - this.g1 = g1; - this.g2 = g2; - this.operator = operator; - } - - public GraphUnion(G g1, G g2) - { - this(g1, g2, WeightCombiner.SUM); - } - - //~ Methods ---------------------------------------------------------------- - - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set res = new HashSet(); - if (g1.containsVertex(sourceVertex) - && g1.containsVertex(targetVertex)) - { - res.addAll(g1.getAllEdges(sourceVertex, targetVertex)); - } - if (g2.containsVertex(sourceVertex) - && g2.containsVertex(targetVertex)) - { - res.addAll(g2.getAllEdges(sourceVertex, targetVertex)); - } - return Collections.unmodifiableSet(res); - } - - public E getEdge(V sourceVertex, V targetVertex) - { - E res = null; - if (g1.containsVertex(sourceVertex) - && g1.containsVertex(targetVertex)) - { - res = g1.getEdge(sourceVertex, targetVertex); - } - if ((res == null) - && g2.containsVertex(sourceVertex) - && g2.containsVertex(targetVertex)) - { - res = g2.getEdge(sourceVertex, targetVertex); - } - return res; - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public EdgeFactory getEdgeFactory() - { - throw new UnsupportedOperationException(READ_ONLY); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public E addEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public boolean addVertex(V v) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - public boolean containsEdge(E e) - { - return g1.containsEdge(e) || g2.containsEdge(e); - } - - public boolean containsVertex(V v) - { - return g1.containsVertex(v) || g2.containsVertex(v); - } - - public Set edgeSet() - { - Set res = new HashSet(); - res.addAll(g1.edgeSet()); - res.addAll(g2.edgeSet()); - return Collections.unmodifiableSet(res); - } - - public Set edgesOf(V vertex) - { - Set res = new HashSet(); - if (g1.containsVertex(vertex)) { - res.addAll(g1.edgesOf(vertex)); - } - if (g2.containsVertex(vertex)) { - res.addAll(g2.edgesOf(vertex)); - } - return Collections.unmodifiableSet(res); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public boolean removeEdge(E e) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - /** - * Throws UnsupportedOperationException, because - * GraphUnion is read-only. - */ - public boolean removeVertex(V v) - { - throw new UnsupportedOperationException(READ_ONLY); - } - - public Set vertexSet() - { - Set res = new HashSet(); - res.addAll(g1.vertexSet()); - res.addAll(g2.vertexSet()); - return Collections.unmodifiableSet(res); - } - - public V getEdgeSource(E e) - { - if (g1.containsEdge(e)) { - return g1.getEdgeSource(e); - } - if (g2.containsEdge(e)) { - return g2.getEdgeSource(e); - } - return null; - } - - public V getEdgeTarget(E e) - { - if (g1.containsEdge(e)) { - return g1.getEdgeTarget(e); - } - if (g2.containsEdge(e)) { - return g2.getEdgeTarget(e); - } - return null; - } - - public double getEdgeWeight(E e) - { - if (g1.containsEdge(e) && g2.containsEdge(e)) { - return operator.combine(g1.getEdgeWeight(e), g2.getEdgeWeight(e)); - } - if (g1.containsEdge(e)) { - return g1.getEdgeWeight(e); - } - if (g2.containsEdge(e)) { - return g2.getEdgeWeight(e); - } - throw new IllegalArgumentException("no such edge in the union"); - } - - /** - * @return G1 - */ - public G getG1() - { - return g1; - } - - /** - * @return G2 - */ - public G getG2() - { - return g2; - } -} - -// End GraphUnion.java diff --git a/src/org/jgrapht/graph/IntrusiveEdge.java b/src/org/jgrapht/graph/IntrusiveEdge.java deleted file mode 100644 index bc7aa36..0000000 --- a/src/org/jgrapht/graph/IntrusiveEdge.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * IntrusiveEdge.java - * ------------------- - * (C) Copyright 2006-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 28-May-2006 : Initial revision (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - - -/** - * IntrusiveEdge encapsulates the internals for the default edge implementation. - * It is not intended to be referenced directly (which is why it's not public); - * use DefaultEdge for that. - * - * @author John V. Sichi - */ -class IntrusiveEdge - implements Cloneable, - Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3258408452177932855L; - - //~ Instance fields -------------------------------------------------------- - - Object source; - - Object target; - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Object#clone() - */ - public Object clone() - { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - // shouldn't happen as we are Cloneable - throw new InternalError(); - } - } -} - -// End IntrusiveEdge.java diff --git a/src/org/jgrapht/graph/ListenableDirectedGraph.java b/src/org/jgrapht/graph/ListenableDirectedGraph.java deleted file mode 100644 index 7b96449..0000000 --- a/src/org/jgrapht/graph/ListenableDirectedGraph.java +++ /dev/null @@ -1,83 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------------- - * ListenableDirectedGraph.java - * ---------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed graph which is also {@link org.jgrapht.ListenableGraph}. - * - * @see DefaultListenableGraph - */ -public class ListenableDirectedGraph - extends DefaultListenableGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3257571698126368824L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new listenable directed graph. - * - * @param edgeClass class on which to base factory for edges - */ - public ListenableDirectedGraph(Class edgeClass) - { - this(new DefaultDirectedGraph(edgeClass)); - } - - /** - * Creates a new listenable directed graph. - * - * @param base the backing graph. - */ - public ListenableDirectedGraph(DirectedGraph base) - { - super(base); - } -} - -// End ListenableDirectedGraph.java diff --git a/src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java b/src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java deleted file mode 100644 index eaff740..0000000 --- a/src/org/jgrapht/graph/ListenableDirectedWeightedGraph.java +++ /dev/null @@ -1,84 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------------ - * ListenableDirectedWeightedGraph.java - * ------------------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id: ListenableDirectedWeightedGraph.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Jun-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed weighted graph which is also {@link org.jgrapht.ListenableGraph}. - * - * @see DefaultListenableGraph - */ -public class ListenableDirectedWeightedGraph - extends ListenableDirectedGraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3977582476627621938L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new listenable directed weighted graph. - * - * @param edgeClass class on which to base factory for edges - */ - public ListenableDirectedWeightedGraph(Class edgeClass) - { - this(new DefaultDirectedWeightedGraph(edgeClass)); - } - - /** - * Creates a new listenable directed weighted graph. - * - * @param base the backing graph. - */ - public ListenableDirectedWeightedGraph(WeightedGraph base) - { - super((DirectedGraph) base); - } -} - -// End ListenableDirectedWeightedGraph.java diff --git a/src/org/jgrapht/graph/ListenableUndirectedGraph.java b/src/org/jgrapht/graph/ListenableUndirectedGraph.java deleted file mode 100644 index 3f44b50..0000000 --- a/src/org/jgrapht/graph/ListenableUndirectedGraph.java +++ /dev/null @@ -1,83 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------ - * ListenableUndirectedGraph.java - * ------------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * An undirected graph which is also {@link org.jgrapht.ListenableGraph}. - * - * @see DefaultListenableGraph - */ -public class ListenableUndirectedGraph - extends DefaultListenableGraph - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3256999969193145905L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new listenable undirected simple graph. - * - * @param edgeClass class on which to base factory for edges - */ - public ListenableUndirectedGraph(Class edgeClass) - { - this(new SimpleGraph(edgeClass)); - } - - /** - * Creates a new listenable undirected graph. - * - * @param base the backing graph. - */ - public ListenableUndirectedGraph(UndirectedGraph base) - { - super(base); - } -} - -// End ListenableUndirectedGraph.java diff --git a/src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java b/src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java deleted file mode 100644 index 1910c50..0000000 --- a/src/org/jgrapht/graph/ListenableUndirectedWeightedGraph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------------------- - * ListenableUndirectedWeightedGraph.java - * -------------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id: ListenableUndirectedWeightedGraph.java 485 2006-06-26 09:12:14Z - * perfecthash $ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Jun-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * An undirected weighted graph which is also {@link - * org.jgrapht.ListenableGraph}. - * - * @see DefaultListenableGraph - */ -public class ListenableUndirectedWeightedGraph - extends ListenableUndirectedGraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3690762799613949747L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new listenable undirected weighted graph. - * - * @param edgeClass class on which to base factory for edges - */ - public ListenableUndirectedWeightedGraph(Class edgeClass) - { - this(new SimpleWeightedGraph(edgeClass)); - } - - /** - * Creates a new listenable undirected weighted graph. - * - * @param base the backing graph. - */ - public ListenableUndirectedWeightedGraph(WeightedGraph base) - { - super((UndirectedGraph) base); - } -} - -// End ListenableUndirectedWeightedGraph.java diff --git a/src/org/jgrapht/graph/MaskEdgeSet.java b/src/org/jgrapht/graph/MaskEdgeSet.java deleted file mode 100644 index 234ad37..0000000 --- a/src/org/jgrapht/graph/MaskEdgeSet.java +++ /dev/null @@ -1,149 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * MaskEdgeSet.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; -import org.jgrapht.util.PrefetchIterator.*; - - -/** - * Helper for {@link MaskSubgraph}. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -class MaskEdgeSet - extends AbstractSet -{ - //~ Instance fields -------------------------------------------------------- - - private Set edgeSet; - - private Graph graph; - - private MaskFunctor mask; - - private transient TypeUtil edgeTypeDecl = null; - - private int size; - - //~ Constructors ----------------------------------------------------------- - - public MaskEdgeSet( - Graph graph, - Set edgeSet, - MaskFunctor mask) - { - this.graph = graph; - this.edgeSet = edgeSet; - this.mask = mask; - this.size = -1; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see java.util.Collection#contains(java.lang.Object) - */ - public boolean contains(Object o) - { - return this.edgeSet.contains(o) - && !this.mask.isEdgeMasked(TypeUtil.uncheckedCast(o, edgeTypeDecl)); - } - - /** - * @see java.util.Set#iterator() - */ - public Iterator iterator() - { - return new PrefetchIterator(new MaskEdgeSetNextElementFunctor()); - } - - /** - * @see java.util.Set#size() - */ - public int size() - { - if (this.size == -1) { - this.size = 0; - for (Iterator iter = iterator(); iter.hasNext();) { - iter.next(); - this.size++; - } - } - return this.size; - } - - //~ Inner Classes ---------------------------------------------------------- - - private class MaskEdgeSetNextElementFunctor - implements NextElementFunctor - { - private Iterator iter; - - public MaskEdgeSetNextElementFunctor() - { - this.iter = MaskEdgeSet.this.edgeSet.iterator(); - } - - public E nextElement() - throws NoSuchElementException - { - E edge = this.iter.next(); - while (isMasked(edge)) { - edge = this.iter.next(); - } - return edge; - } - - private boolean isMasked(E edge) - { - return MaskEdgeSet.this.mask.isEdgeMasked(edge) - || MaskEdgeSet.this.mask.isVertexMasked( - MaskEdgeSet.this.graph.getEdgeSource(edge)) - || MaskEdgeSet.this.mask.isVertexMasked( - MaskEdgeSet.this.graph.getEdgeTarget(edge)); - } - } -} - -// End MaskEdgeSet.java diff --git a/src/org/jgrapht/graph/MaskFunctor.java b/src/org/jgrapht/graph/MaskFunctor.java deleted file mode 100644 index a16547a..0000000 --- a/src/org/jgrapht/graph/MaskFunctor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * MaskFunctor.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -/** - * A functor interface for masking out vertices and edges of a graph. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public interface MaskFunctor -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Returns true if the edge is masked, false - * otherwise. - * - * @param edge edge. - * - * @return . - */ - public boolean isEdgeMasked(E edge); - - /** - * Returns true if the vertex is masked, false - * otherwise. - * - * @param vertex vertex. - * - * @return . - */ - public boolean isVertexMasked(V vertex); -} - -// End MaskFunctor.java diff --git a/src/org/jgrapht/graph/MaskSubgraph.java b/src/org/jgrapht/graph/MaskSubgraph.java deleted file mode 100644 index 18951f5..0000000 --- a/src/org/jgrapht/graph/MaskSubgraph.java +++ /dev/null @@ -1,298 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * MaskSubgraph.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * An unmodifiable subgraph induced by a vertex/edge masking function. The - * subgraph will keep track of edges being added to its vertex subset as well as - * deletion of edges and vertices. When iterating over the vertices/edges, it - * will iterate over the vertices/edges of the base graph and discard - * vertices/edges that are masked (an edge with a masked extremity vertex is - * discarded as well). - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class MaskSubgraph - extends AbstractGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final String UNMODIFIABLE = "this graph is unmodifiable"; - - //~ Instance fields -------------------------------------------------------- - - private Graph base; - - private Set edges; - - private MaskFunctor mask; - - private Set vertices; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new induced subgraph. Running-time = O(1). - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param mask vertices and edges to exclude in the subgraph. If a - * vertex/edge is masked, it is as if it is not in the subgraph. - */ - public MaskSubgraph(Graph base, MaskFunctor mask) - { - super(); - this.base = base; - this.mask = mask; - - this.vertices = new MaskVertexSet(base.vertexSet(), mask); - this.edges = new MaskEdgeSet(base, base.edgeSet(), mask); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - public boolean addEdge(V sourceVertex, V targetVertex, E edge) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - public boolean containsEdge(E e) - { - return edgeSet().contains(e); - } - - public boolean containsVertex(V v) - { - return !this.mask.isVertexMasked(v) && this.base.containsVertex(v); - } - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - return edgesOf(vertex).size(); - } - - public Set edgeSet() - { - return this.edges; - } - - public Set edgesOf(V vertex) - { - assertVertexExist(vertex); - - return new MaskEdgeSet( - this.base, - this.base.edgesOf(vertex), - this.mask); - } - - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set edges = null; - - if (containsVertex(sourceVertex) && containsVertex(targetVertex)) { - return new MaskEdgeSet( - this.base, - this.base.getAllEdges( - sourceVertex, - targetVertex), - this.mask); - } - - return edges; - } - - public E getEdge(V sourceVertex, V targetVertex) - { - Set edges = getAllEdges(sourceVertex, targetVertex); - - if ((edges == null) || edges.isEmpty()) { - return null; - } else { - return edges.iterator().next(); - } - } - - public EdgeFactory getEdgeFactory() - { - return this.base.getEdgeFactory(); - } - - public V getEdgeSource(E edge) - { - assert (edgeSet().contains(edge)); - - return this.base.getEdgeSource(edge); - } - - public V getEdgeTarget(E edge) - { - assert (edgeSet().contains(edge)); - - return this.base.getEdgeTarget(edge); - } - - public double getEdgeWeight(E edge) - { - assert (edgeSet().contains(edge)); - - return this.base.getEdgeWeight(edge); - } - - /** - * @see DirectedGraph#incomingEdgesOf(Object) - */ - public Set incomingEdgesOf(V vertex) - { - assertVertexExist(vertex); - - return new MaskEdgeSet( - this.base, - ((DirectedGraph) this.base).incomingEdgesOf(vertex), - this.mask); - } - - /** - * @see DirectedGraph#inDegreeOf(Object) - */ - public int inDegreeOf(V vertex) - { - return incomingEdgesOf(vertex).size(); - } - - /** - * @see DirectedGraph#outDegreeOf(Object) - */ - public int outDegreeOf(V vertex) - { - return outgoingEdgesOf(vertex).size(); - } - - /** - * @see DirectedGraph#outgoingEdgesOf(Object) - */ - public Set outgoingEdgesOf(V vertex) - { - assertVertexExist(vertex); - - return new MaskEdgeSet( - this.base, - ((DirectedGraph) this.base).outgoingEdgesOf(vertex), - this.mask); - } - - /** - * @see Graph#removeAllEdges(Collection) - */ - public boolean removeAllEdges(Collection edges) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllEdges(Object, Object) - */ - public Set removeAllEdges(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllVertices(Collection) - */ - public boolean removeAllVertices(Collection vertices) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - public Set vertexSet() - { - return this.vertices; - } -} - -// End MaskSubgraph.java diff --git a/src/org/jgrapht/graph/MaskVertexSet.java b/src/org/jgrapht/graph/MaskVertexSet.java deleted file mode 100644 index 5daf256..0000000 --- a/src/org/jgrapht/graph/MaskVertexSet.java +++ /dev/null @@ -1,134 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * MaskVertexSet.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.util.*; -import org.jgrapht.util.PrefetchIterator.*; - - -/** - * Helper for {@link MaskSubgraph}. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -class MaskVertexSet - extends AbstractSet -{ - //~ Instance fields -------------------------------------------------------- - - private MaskFunctor mask; - - private int size; - - private Set vertexSet; - - private transient TypeUtil vertexTypeDecl = null; - - //~ Constructors ----------------------------------------------------------- - - public MaskVertexSet(Set vertexSet, MaskFunctor mask) - { - this.vertexSet = vertexSet; - this.mask = mask; - this.size = -1; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see java.util.Collection#contains(java.lang.Object) - */ - public boolean contains(Object o) - { - return - !this.mask.isVertexMasked(TypeUtil.uncheckedCast(o, vertexTypeDecl)) - && this.vertexSet.contains(o); - } - - /** - * @see java.util.Set#iterator() - */ - public Iterator iterator() - { - return new PrefetchIterator(new MaskVertexSetNextElementFunctor()); - } - - /** - * @see java.util.Set#size() - */ - public int size() - { - if (this.size == -1) { - this.size = 0; - for (Iterator iter = iterator(); iter.hasNext();) { - iter.next(); - this.size++; - } - } - return this.size; - } - - //~ Inner Classes ---------------------------------------------------------- - - private class MaskVertexSetNextElementFunctor - implements NextElementFunctor - { - private Iterator iter; - - public MaskVertexSetNextElementFunctor() - { - this.iter = MaskVertexSet.this.vertexSet.iterator(); - } - - public V nextElement() - throws NoSuchElementException - { - V element = this.iter.next(); - while (MaskVertexSet.this.mask.isVertexMasked(element)) { - element = this.iter.next(); - } - return element; - } - } -} - -// End MaskVertexSet.java diff --git a/src/org/jgrapht/graph/Multigraph.java b/src/org/jgrapht/graph/Multigraph.java deleted file mode 100644 index 5a9150f..0000000 --- a/src/org/jgrapht/graph/Multigraph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------- - * Multigraph.java - * --------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A multigraph. A multigraph is a non-simple undirected graph in which no loops - * are permitted, but multiple edges between any two vertices are. If you're - * unsure about multigraphs, see: - * http://mathworld.wolfram.com/Multigraph.html. - */ -public class Multigraph - extends AbstractBaseGraph - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3257001055819871795L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new multigraph. - * - * @param edgeClass class on which to base factory for edges - */ - public Multigraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new multigraph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public Multigraph(EdgeFactory ef) - { - super(ef, true, false); - } -} - -// End Multigraph.java diff --git a/src/org/jgrapht/graph/ParanoidGraph.java b/src/org/jgrapht/graph/ParanoidGraph.java deleted file mode 100644 index 9b6983a..0000000 --- a/src/org/jgrapht/graph/ParanoidGraph.java +++ /dev/null @@ -1,110 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------- - * ParanoidGraph.java - * ------------------- - * (C) Copyright 2007-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 8-Nov-2007 : Initial revision (JVS); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * ParanoidGraph provides a way to verify that objects added to a graph obey the - * standard equals/hashCode contract. It can be used to wrap an underlying graph - * to be verified. Note that the verification is very expensive, so - * ParanoidGraph should only be used during debugging. - * - * @author John Sichi - * @version $Id$ - */ -public class ParanoidGraph - extends GraphDelegator -{ - //~ Static fields/initializers --------------------------------------------- - - /** - */ - private static final long serialVersionUID = 5075284167422166539L; - - //~ Constructors ----------------------------------------------------------- - - public ParanoidGraph(Graph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - verifyAdd(edgeSet(), e); - return super.addEdge(sourceVertex, targetVertex, e); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - verifyAdd(vertexSet(), v); - return super.addVertex(v); - } - - private static void verifyAdd(Set set, T t) - { - for (T o : set) { - if (o == t) { - continue; - } - if (o.equals(t) && (o.hashCode() != t.hashCode())) { - throw new IllegalArgumentException( - "ParanoidGraph detected objects " - + "o1 (hashCode=" + o.hashCode() - + ") and o2 (hashCode=" + t.hashCode() - + ") where o1.equals(o2) " - + "but o1.hashCode() != o2.hashCode()"); - } - } - } -} - -// End ParanoidGraph.java diff --git a/src/org/jgrapht/graph/Pseudograph.java b/src/org/jgrapht/graph/Pseudograph.java deleted file mode 100644 index 1b4ac16..0000000 --- a/src/org/jgrapht/graph/Pseudograph.java +++ /dev/null @@ -1,84 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * Pseudograph.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A pseudograph. A pseudograph is a non-simple undirected graph in which both - * graph loops and multiple edges are permitted. If you're unsure about - * pseudographs, see: - * http://mathworld.wolfram.com/Pseudograph.html. - */ -public class Pseudograph - extends AbstractBaseGraph - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3833183614484755253L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new pseudograph. - * - * @param edgeClass class on which to base factory for edges - */ - public Pseudograph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new pseudograph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public Pseudograph(EdgeFactory ef) - { - super(ef, true, true); - } -} - -// End Pseudograph.java diff --git a/src/org/jgrapht/graph/SimpleDirectedGraph.java b/src/org/jgrapht/graph/SimpleDirectedGraph.java deleted file mode 100644 index 115c7bd..0000000 --- a/src/org/jgrapht/graph/SimpleDirectedGraph.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------ - * SimpleDirectedGraph.java - * ------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A simple directed graph. A simple directed graph is a directed graph in which - * neither multiple edges between any two vertices nor loops are permitted. - */ -public class SimpleDirectedGraph - extends AbstractBaseGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 4049358608472879671L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new simple directed graph. - * - * @param edgeClass class on which to base factory for edges - */ - public SimpleDirectedGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } - - /** - * Creates a new simple directed graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public SimpleDirectedGraph(EdgeFactory ef) - { - super(ef, false, false); - } -} - -// End SimpleDirectedGraph.java diff --git a/src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java b/src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java deleted file mode 100644 index 089b781..0000000 --- a/src/org/jgrapht/graph/SimpleDirectedWeightedGraph.java +++ /dev/null @@ -1,83 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------------- - * SimpleDirectedWeightedGraph.java - * -------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A simple directed weighted graph. A simple directed weighted graph is a - * simple directed graph for which edges are assigned weights. - */ -public class SimpleDirectedWeightedGraph - extends SimpleDirectedGraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3904960841681220919L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new simple directed weighted graph with the specified edge - * factory. - * - * @param ef the edge factory of the new graph. - */ - public SimpleDirectedWeightedGraph(EdgeFactory ef) - { - super(ef); - } - - /** - * Creates a new simple directed weighted graph. - * - * @param edgeClass class on which to base factory for edges - */ - public SimpleDirectedWeightedGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } -} - -// End SimpleDirectedWeightedGraph.java diff --git a/src/org/jgrapht/graph/SimpleGraph.java b/src/org/jgrapht/graph/SimpleGraph.java deleted file mode 100644 index 50e88e7..0000000 --- a/src/org/jgrapht/graph/SimpleGraph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * SimpleGraph.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): CHristian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A simple graph. A simple graph is an undirected graph for which at most one - * edge connects any two vertices, and loops are not permitted. If you're unsure - * about simple graphs, see: - * http://mathworld.wolfram.com/SimpleGraph.html. - */ -public class SimpleGraph - extends AbstractBaseGraph - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3545796589454112304L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new simple graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public SimpleGraph(EdgeFactory ef) - { - super(ef, false, false); - } - - /** - * Creates a new simple graph. - * - * @param edgeClass class on which to base factory for edges - */ - public SimpleGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } -} - -// End SimpleGraph.java diff --git a/src/org/jgrapht/graph/SimpleWeightedGraph.java b/src/org/jgrapht/graph/SimpleWeightedGraph.java deleted file mode 100644 index 1d2f3f0..0000000 --- a/src/org/jgrapht/graph/SimpleWeightedGraph.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------ - * SimpleWeightedGraph.java - * ------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A simple weighted graph. A simple weighted graph is a simple graph for which - * edges are assigned weights. - */ -public class SimpleWeightedGraph - extends SimpleGraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3906088949100655922L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new simple weighted graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public SimpleWeightedGraph(EdgeFactory ef) - { - super(ef); - } - - /** - * Creates a new simple weighted graph. - * - * @param edgeClass class on which to base factory for edges - */ - public SimpleWeightedGraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } -} - -// End SimpleWeightedGraph.java diff --git a/src/org/jgrapht/graph/Subgraph.java b/src/org/jgrapht/graph/Subgraph.java deleted file mode 100644 index bfb7da5..0000000 --- a/src/org/jgrapht/graph/Subgraph.java +++ /dev/null @@ -1,546 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------- - * Subgraph.java - * ------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 26-Jul-2003 : Accurate constructors to avoid casting problems (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 23-Oct-2003 : Allowed non-listenable graph as base (BN); - * 07-Feb-2004 : Enabled serialization (BN); - * 11-Mar-2004 : Made generic (CH); - * 15-Mar-2004 : Integrity is now checked using Maps (CH); - * 20-Mar-2004 : Cancelled verification of element identity to base graph (BN); - * 21-Sep-2004 : Added induced subgraph (who?) - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; -import org.jgrapht.util.*; - - -/** - * A subgraph is a graph that has a subset of vertices and a subset of edges - * with respect to some base graph. More formally, a subgraph G(V,E) that is - * based on a base graph Gb(Vb,Eb) satisfies the following subgraph - * property: V is a subset of Vb and E is a subset of Eb. Other than - * this property, a subgraph is a graph with any respect and fully complies with - * the Graph interface. - * - *

      If the base graph is a {@link org.jgrapht.ListenableGraph}, the subgraph - * listens on the base graph and guarantees the subgraph property. If an edge or - * a vertex is removed from the base graph, it is automatically removed from the - * subgraph. Subgraph listeners are informed on such removal only if it results - * in a cascaded removal from the subgraph. If the subgraph has been created as - * an induced subgraph it also keeps track of edges being added to its vertices. - * If vertices are added to the base graph, the subgraph remains unaffected.

      - * - *

      If the base graph is not a ListenableGraph, then the subgraph - * property cannot be guaranteed. If edges or vertices are removed from the base - * graph, they are not removed from the subgraph.

      - * - *

      Modifications to Subgraph are allowed as long as the subgraph property is - * maintained. Addition of vertices or edges are allowed as long as they also - * exist in the base graph. Removal of vertices or edges is always allowed. The - * base graph is never affected by any modification made to the - * subgraph.

      - * - *

      A subgraph may provide a "live-window" on a base graph, so that changes - * made to its vertices or edges are immediately reflected in the base graph, - * and vice versa. For that to happen, vertices and edges added to the subgraph - * must be identical (that is, reference-equal and not only value-equal) - * to their respective ones in the base graph. Previous versions of this class - * enforced such identity, at a severe performance cost. Currently it is no - * longer enforced. If you want to achieve a "live-window"functionality, your - * safest tactics would be to NOT override the equals() methods of - * your vertices and edges. If you use a class that has already overridden the - * equals() method, such as String, than you can use a - * wrapper around it, or else use it directly but exercise a great care to avoid - * having different-but-equal instances in the subgraph and the base graph.

      - * - *

      This graph implementation guarantees deterministic vertex and edge set - * ordering (via {@link LinkedHashSet}).

      - * - * @author Barak Naveh - * @see Graph - * @see Set - * @since Jul 18, 2003 - */ -public class Subgraph> - extends AbstractGraph - implements Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3208313055169665387L; - private static final String NO_SUCH_EDGE_IN_BASE = - "no such edge in base graph"; - private static final String NO_SUCH_VERTEX_IN_BASE = - "no such vertex in base graph"; - - //~ Instance fields -------------------------------------------------------- - - // - Set edgeSet = new LinkedHashSet(); // friendly to improve performance - Set vertexSet = new LinkedHashSet(); // friendly to improve - - // performance - - // - private transient Set unmodifiableEdgeSet = null; - private transient Set unmodifiableVertexSet = null; - private G base; - private boolean isInduced = false; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new Subgraph. - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - * @param edgeSubset edges to in include in the subgraph. If - * null then all the edges whose vertices found in the graph - * are included. - */ - public Subgraph(G base, Set vertexSubset, Set edgeSubset) - { - super(); - - this.base = base; - - if (edgeSubset == null) { - isInduced = true; - } - - if (base instanceof ListenableGraph) { - ((ListenableGraph) base).addGraphListener( - new BaseGraphListener()); - } - - addVerticesUsingFilter(base.vertexSet(), vertexSubset); - addEdgesUsingFilter(base.edgeSet(), edgeSubset); - } - - /** - * Creates a new induced Subgraph. The subgraph will keep track of edges - * being added to its vertex subset as well as deletion of edges and - * vertices. If base it not listenable, this is identical to the call - * Subgraph(base, vertexSubset, null) . - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - */ - public Subgraph(G base, Set vertexSubset) - { - this(base, vertexSubset, null); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#getAllEdges(Object, Object) - */ - public Set getAllEdges(V sourceVertex, V targetVertex) - { - Set edges = null; - - if (containsVertex(sourceVertex) && containsVertex(targetVertex)) { - edges = new ArrayUnenforcedSet(); - - Set baseEdges = base.getAllEdges(sourceVertex, targetVertex); - - for (Iterator iter = baseEdges.iterator(); iter.hasNext();) { - E e = iter.next(); - - if (edgeSet.contains(e)) { // add if subgraph also contains - // it - edges.add(e); - } - } - } - - return edges; - } - - /** - * @see Graph#getEdge(Object, Object) - */ - public E getEdge(V sourceVertex, V targetVertex) - { - Set edges = getAllEdges(sourceVertex, targetVertex); - - if ((edges == null) || edges.isEmpty()) { - return null; - } else { - return edges.iterator().next(); - } - } - - /** - * @see Graph#getEdgeFactory() - */ - public EdgeFactory getEdgeFactory() - { - return base.getEdgeFactory(); - } - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - assertVertexExist(sourceVertex); - assertVertexExist(targetVertex); - - if (!base.containsEdge(sourceVertex, targetVertex)) { - throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE); - } - - Set edges = base.getAllEdges(sourceVertex, targetVertex); - - for (Iterator iter = edges.iterator(); iter.hasNext();) { - E e = iter.next(); - - if (!containsEdge(e)) { - edgeSet.add(e); - - return e; - } - } - - return null; - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - if (e == null) { - throw new NullPointerException(); - } - - if (!base.containsEdge(e)) { - throw new IllegalArgumentException(NO_SUCH_EDGE_IN_BASE); - } - - assertVertexExist(sourceVertex); - assertVertexExist(targetVertex); - - assert (base.getEdgeSource(e) == sourceVertex); - assert (base.getEdgeTarget(e) == targetVertex); - - if (containsEdge(e)) { - return false; - } else { - edgeSet.add(e); - - return true; - } - } - - /** - * Adds the specified vertex to this subgraph. - * - * @param v the vertex to be added. - * - * @return true if the vertex was added, otherwise - * false. - * - * @throws NullPointerException - * @throws IllegalArgumentException - * - * @see Subgraph - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - if (v == null) { - throw new NullPointerException(); - } - - if (!base.containsVertex(v)) { - throw new IllegalArgumentException(NO_SUCH_VERTEX_IN_BASE); - } - - if (containsVertex(v)) { - return false; - } else { - vertexSet.add(v); - - return true; - } - } - - /** - * @see Graph#containsEdge(Object) - */ - public boolean containsEdge(E e) - { - return edgeSet.contains(e); - } - - /** - * @see Graph#containsVertex(Object) - */ - public boolean containsVertex(V v) - { - return vertexSet.contains(v); - } - - /** - * @see Graph#edgeSet() - */ - public Set edgeSet() - { - if (unmodifiableEdgeSet == null) { - unmodifiableEdgeSet = Collections.unmodifiableSet(edgeSet); - } - - return unmodifiableEdgeSet; - } - - /** - * @see Graph#edgesOf(Object) - */ - public Set edgesOf(V vertex) - { - assertVertexExist(vertex); - - Set edges = new ArrayUnenforcedSet(); - Set baseEdges = base.edgesOf(vertex); - - for (E e : baseEdges) { - if (containsEdge(e)) { - edges.add(e); - } - } - - return edges; - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - return edgeSet.remove(e); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - E e = getEdge(sourceVertex, targetVertex); - - return edgeSet.remove(e) ? e : null; - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - // If the base graph does NOT contain v it means we are here in - // response to removal of v from the base. In such case we don't need - // to remove all the edges of v as they were already removed. - if (containsVertex(v) && base.containsVertex(v)) { - removeAllEdges(edgesOf(v)); - } - - return vertexSet.remove(v); - } - - /** - * @see Graph#vertexSet() - */ - public Set vertexSet() - { - if (unmodifiableVertexSet == null) { - unmodifiableVertexSet = Collections.unmodifiableSet(vertexSet); - } - - return unmodifiableVertexSet; - } - - /** - * @see Graph#getEdgeSource(Object) - */ - public V getEdgeSource(E e) - { - return base.getEdgeSource(e); - } - - /** - * @see Graph#getEdgeTarget(Object) - */ - public V getEdgeTarget(E e) - { - return base.getEdgeTarget(e); - } - - private void addEdgesUsingFilter(Set edgeSet, Set filter) - { - E e; - boolean containsVertices; - boolean edgeIncluded; - - for (Iterator iter = edgeSet.iterator(); iter.hasNext();) { - e = iter.next(); - - V sourceVertex = base.getEdgeSource(e); - V targetVertex = base.getEdgeTarget(e); - containsVertices = - containsVertex(sourceVertex) - && containsVertex(targetVertex); - - // note the use of short circuit evaluation - edgeIncluded = (filter == null) || filter.contains(e); - - if (containsVertices && edgeIncluded) { - addEdge(sourceVertex, targetVertex, e); - } - } - } - - private void addVerticesUsingFilter(Set vertexSet, Set filter) - { - V v; - - for (Iterator iter = vertexSet.iterator(); iter.hasNext();) { - v = iter.next(); - - // note the use of short circuit evaluation - if ((filter == null) || filter.contains(v)) { - addVertex(v); - } - } - } - - public G getBase() - { - return base; - } - - /** - * @see Graph#getEdgeWeight(Object) - */ - public double getEdgeWeight(E e) - { - return base.getEdgeWeight(e); - } - - /** - * @see WeightedGraph#setEdgeWeight(Object, double) - */ - public void setEdgeWeight(E e, double weight) - { - ((WeightedGraph) base).setEdgeWeight(e, weight); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * An internal listener on the base graph. - * - * @author Barak Naveh - * @since Jul 20, 2003 - */ - private class BaseGraphListener - implements GraphListener, - Serializable - { - private static final long serialVersionUID = 4343535244243546391L; - - /** - * @see GraphListener#edgeAdded(GraphEdgeChangeEvent) - */ - public void edgeAdded(GraphEdgeChangeEvent e) - { - if (isInduced) { - E edge = e.getEdge(); - V source = e.getEdgeSource(); - V target = e.getEdgeTarget(); - if (containsVertex(source) && containsVertex(target)) { - addEdge( - source, - target, - edge); - } - } - } - - /** - * @see GraphListener#edgeRemoved(GraphEdgeChangeEvent) - */ - public void edgeRemoved(GraphEdgeChangeEvent e) - { - E edge = e.getEdge(); - - removeEdge(edge); - } - - /** - * @see VertexSetListener#vertexAdded(GraphVertexChangeEvent) - */ - public void vertexAdded(GraphVertexChangeEvent e) - { - // we don't care - } - - /** - * @see VertexSetListener#vertexRemoved(GraphVertexChangeEvent) - */ - public void vertexRemoved(GraphVertexChangeEvent e) - { - V vertex = e.getVertex(); - - removeVertex(vertex); - } - } -} - -// End Subgraph.java diff --git a/src/org/jgrapht/graph/UndirectedGraphUnion.java b/src/org/jgrapht/graph/UndirectedGraphUnion.java deleted file mode 100644 index f6c4577..0000000 --- a/src/org/jgrapht/graph/UndirectedGraphUnion.java +++ /dev/null @@ -1,81 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * UndirectedGraphUnion.java - * ------------------------- - * (C) Copyright 2009-2009, by Ilya Razenshteyn - * - * Original Author: Ilya Razenshteyn and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 02-Feb-2009 : Initial revision (IR); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -public class UndirectedGraphUnion - extends GraphUnion> - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -740199233080172450L; - - //~ Constructors ----------------------------------------------------------- - - UndirectedGraphUnion( - UndirectedGraph g1, - UndirectedGraphUnion g2, - WeightCombiner operator) - { - super(g1, g2, operator); - } - - UndirectedGraphUnion( - UndirectedGraph g1, - UndirectedGraphUnion g2) - { - super(g1, g2); - } - - //~ Methods ---------------------------------------------------------------- - - public int degreeOf(V vertex) - { - Set res = edgesOf(vertex); - return res.size(); - } -} - -// End UndirectedGraphUnion.java diff --git a/src/org/jgrapht/graph/UndirectedMaskSubgraph.java b/src/org/jgrapht/graph/UndirectedMaskSubgraph.java deleted file mode 100644 index 63c9fc6..0000000 --- a/src/org/jgrapht/graph/UndirectedMaskSubgraph.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * UndirectedMaskSubgraph.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * An undirected graph that is a {@link MaskSubgraph} on another graph. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class UndirectedMaskSubgraph - extends MaskSubgraph - implements UndirectedGraph -{ - //~ Constructors ----------------------------------------------------------- - - public UndirectedMaskSubgraph( - UndirectedGraph base, - MaskFunctor mask) - { - super(base, mask); - } -} - -// End UndirectedMaskSubgraph.java diff --git a/src/org/jgrapht/graph/UndirectedSubgraph.java b/src/org/jgrapht/graph/UndirectedSubgraph.java deleted file mode 100644 index 381fa99..0000000 --- a/src/org/jgrapht/graph/UndirectedSubgraph.java +++ /dev/null @@ -1,106 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------- - * UndirectedSubgraph.java - * ----------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * An undirected graph that is a subgraph on other graph. - * - * @see Subgraph - */ -public class UndirectedSubgraph - extends Subgraph> - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3256728359772631350L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new undirected subgraph. - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - * @param edgeSubset edges to in include in the subgraph. If - * null then all the edges whose vertices found in the graph - * are included. - */ - public UndirectedSubgraph( - UndirectedGraph base, - Set vertexSubset, - Set edgeSubset) - { - super(base, vertexSubset, edgeSubset); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see UndirectedGraph#degreeOf(Object) - */ - public int degreeOf(V vertex) - { - assertVertexExist(vertex); - - int degree = 0; - - for (E e : getBase().edgesOf(vertex)) { - if (containsEdge(e)) { - degree++; - - if (getEdgeSource(e).equals(getEdgeTarget(e))) { - degree++; - } - } - } - - return degree; - } -} - -// End UndirectedSubgraph.java diff --git a/src/org/jgrapht/graph/UndirectedWeightedSubgraph.java b/src/org/jgrapht/graph/UndirectedWeightedSubgraph.java deleted file mode 100644 index b7bde41..0000000 --- a/src/org/jgrapht/graph/UndirectedWeightedSubgraph.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------- - * UndirectedWeightedSubgraph.java - * ------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * - */ -package org.jgrapht.graph; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * An undirected weighted graph that is a subgraph on other graph. - * - * @see Subgraph - */ -public class UndirectedWeightedSubgraph - extends UndirectedSubgraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3689346615735236409L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new undirected weighted subgraph. - * - * @param base the base (backing) graph on which the subgraph will be based. - * @param vertexSubset vertices to include in the subgraph. If - * null then all vertices are included. - * @param edgeSubset edges to in include in the subgraph. If - * null then all the edges whose vertices found in the graph - * are included. - */ - public UndirectedWeightedSubgraph( - WeightedGraph base, - Set vertexSubset, - Set edgeSubset) - { - super((UndirectedGraph) base, vertexSubset, edgeSubset); - } -} - -// End UndirectedWeightedSubgraph.java diff --git a/src/org/jgrapht/graph/UnmodifiableDirectedGraph.java b/src/org/jgrapht/graph/UnmodifiableDirectedGraph.java deleted file mode 100644 index 67ec241..0000000 --- a/src/org/jgrapht/graph/UnmodifiableDirectedGraph.java +++ /dev/null @@ -1,74 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------------ - * UnmodifiableDirectedGraph.java - * ------------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A directed graph that cannot be modified. - * - * @see UnmodifiableGraph - */ -public class UnmodifiableDirectedGraph - extends UnmodifiableGraph - implements DirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3978701783725913906L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new unmodifiable directed graph based on the specified backing - * graph. - * - * @param g the backing graph on which an unmodifiable graph is to be - * created. - */ - public UnmodifiableDirectedGraph(DirectedGraph g) - { - super(g); - } -} - -// End UnmodifiableDirectedGraph.java diff --git a/src/org/jgrapht/graph/UnmodifiableGraph.java b/src/org/jgrapht/graph/UnmodifiableGraph.java deleted file mode 100644 index 6455120..0000000 --- a/src/org/jgrapht/graph/UnmodifiableGraph.java +++ /dev/null @@ -1,164 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * UnmodifiableGraph.java - * ---------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import java.io.*; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * An unmodifiable view of the backing graph specified in the constructor. This - * graph allows modules to provide users with "read-only" access to internal - * graphs. Query operations on this graph "read through" to the backing graph, - * and attempts to modify this graph result in an - * UnsupportedOperationException. - * - *

      This graph does not pass the hashCode and equals operations through - * to the backing graph, but relies on Object's equals and - * hashCode methods. This graph will be serializable if the backing - * graph is serializable.

      - * - * @author Barak Naveh - * @since Jul 24, 2003 - */ -public class UnmodifiableGraph - extends GraphDelegator - implements Serializable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3544957670722713913L; - private static final String UNMODIFIABLE = "this graph is unmodifiable"; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new unmodifiable graph based on the specified backing graph. - * - * @param g the backing graph on which an unmodifiable graph is to be - * created. - */ - public UnmodifiableGraph(Graph g) - { - super(g); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see Graph#addEdge(Object, Object) - */ - public E addEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#addEdge(Object, Object, Object) - */ - public boolean addEdge(V sourceVertex, V targetVertex, E e) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#addVertex(Object) - */ - public boolean addVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllEdges(Collection) - */ - public boolean removeAllEdges(Collection edges) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllEdges(Object, Object) - */ - public Set removeAllEdges(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeAllVertices(Collection) - */ - public boolean removeAllVertices(Collection vertices) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(Object) - */ - public boolean removeEdge(E e) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeEdge(Object, Object) - */ - public E removeEdge(V sourceVertex, V targetVertex) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } - - /** - * @see Graph#removeVertex(Object) - */ - public boolean removeVertex(V v) - { - throw new UnsupportedOperationException(UNMODIFIABLE); - } -} - -// End UnmodifiableGraph.java diff --git a/src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java b/src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java deleted file mode 100644 index 2024ac9..0000000 --- a/src/org/jgrapht/graph/UnmodifiableUndirectedGraph.java +++ /dev/null @@ -1,74 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------------- - * UnmodifiableUndirectedGraph.java - * -------------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH) - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * An undirected graph that cannot be modified. - * - * @see UnmodifiableGraph - */ -public class UnmodifiableUndirectedGraph - extends UnmodifiableGraph - implements UndirectedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3258134639355704624L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new unmodifiable undirected graph based on the specified - * backing graph. - * - * @param g the backing graph on which an unmodifiable graph is to be - * created. - */ - public UnmodifiableUndirectedGraph(UndirectedGraph g) - { - super(g); - } -} - -// End UnmodifiableUndirectedGraph.java diff --git a/src/org/jgrapht/graph/WeightedMultigraph.java b/src/org/jgrapht/graph/WeightedMultigraph.java deleted file mode 100644 index 339f55e..0000000 --- a/src/org/jgrapht/graph/WeightedMultigraph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------- - * WeightedMultigraph.java - * ----------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A weighted multigraph. A weighted multigraph is a non-simple undirected graph - * in which no loops are permitted, but multiple edges between any two vertices - * are. The edges of a weighted multigraph have weights. If you're unsure about - * multigraphs, see: - * http://mathworld.wolfram.com/Multigraph.html. - */ -public class WeightedMultigraph - extends Multigraph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3544671793370640696L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new weighted multigraph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public WeightedMultigraph(EdgeFactory ef) - { - super(ef); - } - - /** - * Creates a new weighted multigraph. - * - * @param edgeClass class on which to base factory for edges - */ - public WeightedMultigraph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } -} - -// End WeightedMultigraph.java diff --git a/src/org/jgrapht/graph/WeightedPseudograph.java b/src/org/jgrapht/graph/WeightedPseudograph.java deleted file mode 100644 index f8b1030..0000000 --- a/src/org/jgrapht/graph/WeightedPseudograph.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------ - * WeightedPseudograph.java - * ------------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 05-Aug-2003 : Initial revision (BN); - * 06-Aug-2005 : Made generic (CH); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht.graph; - -import org.jgrapht.*; - - -/** - * A weighted pseudograph. A weighted pseudograph is a non-simple undirected - * graph in which both graph loops and multiple edges are permitted. The edges - * of a weighted pseudograph have weights. If you're unsure about pseudographs, - * see: - * http://mathworld.wolfram.com/Pseudograph.html. - */ -public class WeightedPseudograph - extends Pseudograph - implements WeightedGraph -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3257290244524356152L; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new weighted pseudograph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public WeightedPseudograph(EdgeFactory ef) - { - super(ef); - } - - /** - * Creates a new weighted pseudograph. - * - * @param edgeClass class on which to base factory for edges - */ - public WeightedPseudograph(Class edgeClass) - { - this(new ClassBasedEdgeFactory(edgeClass)); - } -} - -// End WeightedPseudograph.java diff --git a/src/org/jgrapht/graph/package.html b/src/org/jgrapht/graph/package.html deleted file mode 100644 index 10fca41..0000000 --- a/src/org/jgrapht/graph/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Implementations of various graphs. - - \ No newline at end of file diff --git a/src/org/jgrapht/package.html b/src/org/jgrapht/package.html deleted file mode 100644 index 76a5567..0000000 --- a/src/org/jgrapht/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - -The front-end API's interfaces and classes, including {@link org.jgrapht.Graph}, -{@link org.jgrapht.DirectedGraph} and {@link org.jgrapht.UndirectedGraph}. - - diff --git a/src/org/jgrapht/traverse/AbstractGraphIterator.java b/src/org/jgrapht/traverse/AbstractGraphIterator.java deleted file mode 100644 index 5ab37b5..0000000 --- a/src/org/jgrapht/traverse/AbstractGraphIterator.java +++ /dev/null @@ -1,217 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * AbstractGraphIterator.java - * -------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Aug-2003 : Adaptation to new event model (BN); - * 04-May-2004 : Made generic (CH) - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.event.*; - - -/** - * An empty implementation of a graph iterator to minimize the effort required - * to implement graph iterators. - * - * @author Barak Naveh - * @since Jul 19, 2003 - */ -public abstract class AbstractGraphIterator - implements GraphIterator -{ - //~ Instance fields -------------------------------------------------------- - - private List> traversalListeners = - new ArrayList>(); - private boolean crossComponentTraversal = true; - private boolean reuseEvents = false; - - // We keep this cached redundantly with traversalListeners.size() - // so that subclasses can use it as a fast check to see if - // event firing calls can be skipped. - protected int nListeners = 0; - - //~ Methods ---------------------------------------------------------------- - - /** - * Sets the cross component traversal flag - indicates whether to traverse - * the graph across connected components. - * - * @param crossComponentTraversal if true traverses across - * connected components. - */ - public void setCrossComponentTraversal(boolean crossComponentTraversal) - { - this.crossComponentTraversal = crossComponentTraversal; - } - - /** - * Test whether this iterator is set to traverse the graph across connected - * components. - * - * @return true if traverses across connected components, - * otherwise false. - */ - public boolean isCrossComponentTraversal() - { - return crossComponentTraversal; - } - - /** - * @see GraphIterator#setReuseEvents(boolean) - */ - public void setReuseEvents(boolean reuseEvents) - { - this.reuseEvents = reuseEvents; - } - - /** - * @see GraphIterator#isReuseEvents() - */ - public boolean isReuseEvents() - { - return reuseEvents; - } - - /** - * Adds the specified traversal listener to this iterator. - * - * @param l the traversal listener to be added. - */ - public void addTraversalListener(TraversalListener l) - { - if (!traversalListeners.contains(l)) { - traversalListeners.add(l); - nListeners = traversalListeners.size(); - } - } - - /** - * Unsupported. - * - * @throws UnsupportedOperationException - */ - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Removes the specified traversal listener from this iterator. - * - * @param l the traversal listener to be removed. - */ - public void removeTraversalListener(TraversalListener l) - { - traversalListeners.remove(l); - nListeners = traversalListeners.size(); - } - - /** - * Informs all listeners that the traversal of the current connected - * component finished. - * - * @param e the connected component finished event. - */ - protected void fireConnectedComponentFinished( - ConnectedComponentTraversalEvent e) - { - for (int i = 0; i < nListeners; i++) { - TraversalListener l = traversalListeners.get(i); - l.connectedComponentFinished(e); - } - } - - /** - * Informs all listeners that a traversal of a new connected component has - * started. - * - * @param e the connected component started event. - */ - protected void fireConnectedComponentStarted( - ConnectedComponentTraversalEvent e) - { - for (int i = 0; i < nListeners; i++) { - TraversalListener l = traversalListeners.get(i); - l.connectedComponentStarted(e); - } - } - - /** - * Informs all listeners that a the specified edge was visited. - * - * @param e the edge traversal event. - */ - protected void fireEdgeTraversed(EdgeTraversalEvent e) - { - for (int i = 0; i < nListeners; i++) { - TraversalListener l = traversalListeners.get(i); - l.edgeTraversed(e); - } - } - - /** - * Informs all listeners that a the specified vertex was visited. - * - * @param e the vertex traversal event. - */ - protected void fireVertexTraversed(VertexTraversalEvent e) - { - for (int i = 0; i < nListeners; i++) { - TraversalListener l = traversalListeners.get(i); - l.vertexTraversed(e); - } - } - - /** - * Informs all listeners that a the specified vertex was finished. - * - * @param e the vertex traversal event. - */ - protected void fireVertexFinished(VertexTraversalEvent e) - { - for (int i = 0; i < nListeners; i++) { - TraversalListener l = traversalListeners.get(i); - l.vertexFinished(e); - } - } -} - -// End AbstractGraphIterator.java diff --git a/src/org/jgrapht/traverse/BreadthFirstIterator.java b/src/org/jgrapht/traverse/BreadthFirstIterator.java deleted file mode 100644 index a053588..0000000 --- a/src/org/jgrapht/traverse/BreadthFirstIterator.java +++ /dev/null @@ -1,130 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BreadthFirstIterator.java - * ------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Liviu Rau - * Christian Hammer - * Ross Judson - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 06-Aug-2003 : Extracted common logic to TraverseUtils.XXFirstIterator (BN); - * 31-Jan-2004 : Reparented and changed interface to parent class (BN); - * 28-Sep-2008 : Optimized using ArrayDeque per suggestion from Ross (JVS) - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * A breadth-first iterator for a directed and an undirected graph. For this - * iterator to work correctly the graph must not be modified during iteration. - * Currently there are no means to ensure that, nor to fail-fast. The results of - * such modifications are undefined. - * - * @author Barak Naveh - * @since Jul 19, 2003 - */ -public class BreadthFirstIterator - extends CrossComponentIterator -{ - //~ Instance fields -------------------------------------------------------- - - private Deque queue = new ArrayDeque(); - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new breadth-first iterator for the specified graph. - * - * @param g the graph to be iterated. - */ - public BreadthFirstIterator(Graph g) - { - this(g, null); - } - - /** - * Creates a new breadth-first iterator for the specified graph. Iteration - * will start at the specified start vertex and will be limited to the - * connected component that includes that vertex. If the specified start - * vertex is null, iteration will start at an arbitrary vertex - * and will not be limited, that is, will be able to traverse all the graph. - * - * @param g the graph to be iterated. - * @param startVertex the vertex iteration to be started. - */ - public BreadthFirstIterator(Graph g, V startVertex) - { - super(g, startVertex); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see CrossComponentIterator#isConnectedComponentExhausted() - */ - protected boolean isConnectedComponentExhausted() - { - return queue.isEmpty(); - } - - /** - * @see CrossComponentIterator#encounterVertex(Object, Object) - */ - protected void encounterVertex(V vertex, E edge) - { - putSeenData(vertex, null); - queue.add(vertex); - } - - /** - * @see CrossComponentIterator#encounterVertexAgain(Object, Object) - */ - protected void encounterVertexAgain(V vertex, E edge) - { - } - - /** - * @see CrossComponentIterator#provideNextVertex() - */ - protected V provideNextVertex() - { - return queue.removeFirst(); - } -} - -// End BreadthFirstIterator.java diff --git a/src/org/jgrapht/traverse/ClosestFirstIterator.java b/src/org/jgrapht/traverse/ClosestFirstIterator.java deleted file mode 100644 index 970fb38..0000000 --- a/src/org/jgrapht/traverse/ClosestFirstIterator.java +++ /dev/null @@ -1,338 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * ClosestFirstIterator.java - * ------------------------- - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Barak Naveh - * - * $Id$ - * - * Changes - * ------- - * 02-Sep-2003 : Initial revision (JVS); - * 31-Jan-2004 : Reparented and changed interface to parent class (BN); - * 29-May-2005 : Added radius support (JVS); - * 06-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.traverse; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * A closest-first iterator for a directed or undirected graph. For this - * iterator to work correctly the graph must not be modified during iteration. - * Currently there are no means to ensure that, nor to fail-fast. The results of - * such modifications are undefined. - * - *

      The metric for closest here is the path length from a start vertex. - * Graph.getEdgeWeight(Edge) is summed to calculate path length. Negative edge - * weights will result in an IllegalArgumentException. Optionally, path length - * may be bounded by a finite radius.

      - * - * @author John V. Sichi - * @since Sep 2, 2003 - */ -public class ClosestFirstIterator - extends CrossComponentIterator>> -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Priority queue of fringe vertices. - */ - private FibonacciHeap> heap = - new FibonacciHeap>(); - - /** - * Maximum distance to search. - */ - private double radius = Double.POSITIVE_INFINITY; - - private boolean initialized = false; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new closest-first iterator for the specified graph. - * - * @param g the graph to be iterated. - */ - public ClosestFirstIterator(Graph g) - { - this(g, null); - } - - /** - * Creates a new closest-first iterator for the specified graph. Iteration - * will start at the specified start vertex and will be limited to the - * connected component that includes that vertex. If the specified start - * vertex is null, iteration will start at an arbitrary vertex - * and will not be limited, that is, will be able to traverse all the graph. - * - * @param g the graph to be iterated. - * @param startVertex the vertex iteration to be started. - */ - public ClosestFirstIterator(Graph g, V startVertex) - { - this(g, startVertex, Double.POSITIVE_INFINITY); - } - - /** - * Creates a new radius-bounded closest-first iterator for the specified - * graph. Iteration will start at the specified start vertex and will be - * limited to the subset of the connected component which includes that - * vertex and is reachable via paths of length less than or equal to the - * specified radius. The specified start vertex may not be - * null. - * - * @param g the graph to be iterated. - * @param startVertex the vertex iteration to be started. - * @param radius limit on path length, or Double.POSITIVE_INFINITY for - * unbounded search. - */ - public ClosestFirstIterator(Graph g, V startVertex, double radius) - { - super(g, startVertex); - this.radius = radius; - checkRadiusTraversal(isCrossComponentTraversal()); - initialized = true; - } - - //~ Methods ---------------------------------------------------------------- - - // override AbstractGraphIterator - public void setCrossComponentTraversal(boolean crossComponentTraversal) - { - if (initialized) { - checkRadiusTraversal(crossComponentTraversal); - } - super.setCrossComponentTraversal(crossComponentTraversal); - } - - /** - * Get the length of the shortest path known to the given vertex. If the - * vertex has already been visited, then it is truly the shortest path - * length; otherwise, it is the best known upper bound. - * - * @param vertex vertex being sought from start vertex - * - * @return length of shortest path known, or Double.POSITIVE_INFINITY if no - * path found yet - */ - public double getShortestPathLength(V vertex) - { - FibonacciHeapNode> node = getSeenData(vertex); - - if (node == null) { - return Double.POSITIVE_INFINITY; - } - - return node.getKey(); - } - - /** - * Get the spanning tree edge reaching a vertex which has been seen already - * in this traversal. This edge is the last link in the shortest known path - * between the start vertex and the requested vertex. If the vertex has - * already been visited, then it is truly the minimum spanning tree edge; - * otherwise, it is the best candidate seen so far. - * - * @param vertex the spanned vertex. - * - * @return the spanning tree edge, or null if the vertex either has not been - * seen yet or is the start vertex. - */ - public E getSpanningTreeEdge(V vertex) - { - FibonacciHeapNode> node = getSeenData(vertex); - - if (node == null) { - return null; - } - - return node.getData().spanningTreeEdge; - } - - /** - * @see CrossComponentIterator#isConnectedComponentExhausted() - */ - protected boolean isConnectedComponentExhausted() - { - if (heap.size() == 0) { - return true; - } else { - if (heap.min().getKey() > radius) { - heap.clear(); - - return true; - } else { - return false; - } - } - } - - /** - * @see CrossComponentIterator#encounterVertex(Object, Object) - */ - protected void encounterVertex(V vertex, E edge) - { - double shortestPathLength; - if (edge == null) { - shortestPathLength = 0; - } else { - shortestPathLength = calculatePathLength(vertex, edge); - } - FibonacciHeapNode> node = createSeenData(vertex, edge); - putSeenData(vertex, node); - heap.insert(node, shortestPathLength); - } - - /** - * Override superclass. When we see a vertex again, we need to see if the - * new edge provides a shorter path than the old edge. - * - * @param vertex the vertex re-encountered - * @param edge the edge via which the vertex was re-encountered - */ - protected void encounterVertexAgain(V vertex, E edge) - { - FibonacciHeapNode> node = getSeenData(vertex); - - if (node.getData().frozen) { - // no improvement for this vertex possible - return; - } - - double candidatePathLength = calculatePathLength(vertex, edge); - - if (candidatePathLength < node.getKey()) { - node.getData().spanningTreeEdge = edge; - heap.decreaseKey(node, candidatePathLength); - } - } - - /** - * @see CrossComponentIterator#provideNextVertex() - */ - protected V provideNextVertex() - { - FibonacciHeapNode> node = heap.removeMin(); - node.getData().frozen = true; - - return node.getData().vertex; - } - - private void assertNonNegativeEdge(E edge) - { - if (getGraph().getEdgeWeight(edge) < 0) { - throw new IllegalArgumentException( - "negative edge weights not allowed"); - } - } - - /** - * Determine path length to a vertex via an edge, using the path length for - * the opposite vertex. - * - * @param vertex the vertex for which to calculate the path length. - * @param edge the edge via which the path is being extended. - * - * @return calculated path length. - */ - private double calculatePathLength(V vertex, E edge) - { - assertNonNegativeEdge(edge); - - V otherVertex = Graphs.getOppositeVertex(getGraph(), edge, vertex); - FibonacciHeapNode> otherEntry = - getSeenData(otherVertex); - - return otherEntry.getKey() - + getGraph().getEdgeWeight(edge); - } - - private void checkRadiusTraversal(boolean crossComponentTraversal) - { - if (crossComponentTraversal && (radius != Double.POSITIVE_INFINITY)) { - throw new IllegalArgumentException( - "radius may not be specified for cross-component traversal"); - } - } - - /** - * The first time we see a vertex, make up a new heap node for it. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - * - * @return the new heap node. - */ - private FibonacciHeapNode> createSeenData( - V vertex, - E edge) - { - QueueEntry entry = new QueueEntry(); - entry.vertex = vertex; - entry.spanningTreeEdge = edge; - - return new FibonacciHeapNode>(entry); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Private data to associate with each entry in the priority queue. - */ - static class QueueEntry - { - /** - * Best spanning tree edge to vertex seen so far. - */ - E spanningTreeEdge; - - /** - * The vertex reached. - */ - V vertex; - - /** - * True once spanningTreeEdge is guaranteed to be the true minimum. - */ - boolean frozen; - - QueueEntry() - { - } - } -} - -// End ClosestFirstIterator.java diff --git a/src/org/jgrapht/traverse/CrossComponentIterator.java b/src/org/jgrapht/traverse/CrossComponentIterator.java deleted file mode 100644 index dbf1599..0000000 --- a/src/org/jgrapht/traverse/CrossComponentIterator.java +++ /dev/null @@ -1,570 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* --------------------------- - * CrossComponentIterator.java - * --------------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): John V. Sichi - * Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 31-Jul-2003 : Initial revision (BN); - * 11-Aug-2003 : Adaptation to new event model (BN); - * 31-Jan-2004 : Extracted cross-component traversal functionality (BN); - * 04-May-2004 : Made generic (CH) - * 07-May-2006 : Changed from List to Set (JVS); - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.event.*; - - -/** - * Provides a cross-connected-component traversal functionality for iterator - * subclasses. - * - * @param vertex type - * @param edge type - * @param type of data associated to seen vertices - * - * @author Barak Naveh - * @since Jan 31, 2004 - */ -public abstract class CrossComponentIterator - extends AbstractGraphIterator -{ - //~ Static fields/initializers --------------------------------------------- - - private static final int CCS_BEFORE_COMPONENT = 1; - private static final int CCS_WITHIN_COMPONENT = 2; - private static final int CCS_AFTER_COMPONENT = 3; - - //~ Enums ------------------------------------------------------------------ - - /** - * Standard vertex visit state enumeration. - */ - protected static enum VisitColor - { - /** - * Vertex has not been returned via iterator yet. - */ - WHITE, - - /** - * Vertex has been returned via iterator, but we're not done with all of - * its out-edges yet. - */ - GRAY, - - /** - * Vertex has been returned via iterator, and we're done with all of its - * out-edges. - */ - BLACK - } - - //~ Instance fields -------------------------------------------------------- - - // - private final ConnectedComponentTraversalEvent ccFinishedEvent = - new ConnectedComponentTraversalEvent( - this, - ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_FINISHED); - private final ConnectedComponentTraversalEvent ccStartedEvent = - new ConnectedComponentTraversalEvent( - this, - ConnectedComponentTraversalEvent.CONNECTED_COMPONENT_STARTED); - - // TODO: support ConcurrentModificationException if graph modified - // during iteration. - private FlyweightEdgeEvent reusableEdgeEvent; - private FlyweightVertexEvent reusableVertexEvent; - private Iterator vertexIterator = null; - - /** - * Stores the vertices that have been seen during iteration and (optionally) - * some additional traversal info regarding each vertex. - */ - private Map seen = new HashMap(); - private V startVertex; - private Specifics specifics; - - private final Graph graph; - - /** - * The connected component state - */ - private int state = CCS_BEFORE_COMPONENT; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new iterator for the specified graph. Iteration will start at - * the specified start vertex. If the specified start vertex is - * null, Iteration will start at an arbitrary graph vertex. - * - * @param g the graph to be iterated. - * @param startVertex the vertex iteration to be started. - * - * @throws IllegalArgumentException if g==null or does not - * contain startVertex - */ - public CrossComponentIterator(Graph g, V startVertex) - { - super(); - - if (g == null) { - throw new IllegalArgumentException("graph must not be null"); - } - graph = g; - - specifics = createGraphSpecifics(g); - vertexIterator = g.vertexSet().iterator(); - setCrossComponentTraversal(startVertex == null); - - reusableEdgeEvent = new FlyweightEdgeEvent(this, null); - reusableVertexEvent = new FlyweightVertexEvent(this, null); - - if (startVertex == null) { - // pick a start vertex if graph not empty - if (vertexIterator.hasNext()) { - this.startVertex = vertexIterator.next(); - } else { - this.startVertex = null; - } - } else if (g.containsVertex(startVertex)) { - this.startVertex = startVertex; - } else { - throw new IllegalArgumentException( - "graph must contain the start vertex"); - } - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @return the graph being traversed - */ - public Graph getGraph() - { - return graph; - } - - /** - * @see java.util.Iterator#hasNext() - */ - public boolean hasNext() - { - if (startVertex != null) { - encounterStartVertex(); - } - - if (isConnectedComponentExhausted()) { - if (state == CCS_WITHIN_COMPONENT) { - state = CCS_AFTER_COMPONENT; - if (nListeners != 0) { - fireConnectedComponentFinished(ccFinishedEvent); - } - } - - if (isCrossComponentTraversal()) { - while (vertexIterator.hasNext()) { - V v = vertexIterator.next(); - - if (!isSeenVertex(v)) { - encounterVertex(v, null); - state = CCS_BEFORE_COMPONENT; - - return true; - } - } - - return false; - } else { - return false; - } - } else { - return true; - } - } - - /** - * @see java.util.Iterator#next() - */ - public V next() - { - if (startVertex != null) { - encounterStartVertex(); - } - - if (hasNext()) { - if (state == CCS_BEFORE_COMPONENT) { - state = CCS_WITHIN_COMPONENT; - if (nListeners != 0) { - fireConnectedComponentStarted(ccStartedEvent); - } - } - - V nextVertex = provideNextVertex(); - if (nListeners != 0) { - fireVertexTraversed(createVertexTraversalEvent(nextVertex)); - } - - addUnseenChildrenOf(nextVertex); - - return nextVertex; - } else { - throw new NoSuchElementException(); - } - } - - /** - * Returns true if there are no more uniterated vertices in the - * currently iterated connected component; false otherwise. - * - * @return true if there are no more uniterated vertices in the - * currently iterated connected component; false otherwise. - */ - protected abstract boolean isConnectedComponentExhausted(); - - /** - * Update data structures the first time we see a vertex. - * - * @param vertex the vertex encountered - * @param edge the edge via which the vertex was encountered, or null if the - * vertex is a starting point - */ - protected abstract void encounterVertex(V vertex, E edge); - - /** - * Returns the vertex to be returned in the following call to the iterator - * next method. - * - * @return the next vertex to be returned by this iterator. - */ - protected abstract V provideNextVertex(); - - /** - * Access the data stored for a seen vertex. - * - * @param vertex a vertex which has already been seen. - * - * @return data associated with the seen vertex or null if no - * data was associated with the vertex. A null return can also - * indicate that the vertex was explicitly associated with - * null. - */ - protected D getSeenData(V vertex) - { - return seen.get(vertex); - } - - /** - * Determines whether a vertex has been seen yet by this traversal. - * - * @param vertex vertex in question - * - * @return true if vertex has already been seen - */ - protected boolean isSeenVertex(Object vertex) - { - return seen.containsKey(vertex); - } - - /** - * Called whenever we re-encounter a vertex. The default implementation does - * nothing. - * - * @param vertex the vertex re-encountered - * @param edge the edge via which the vertex was re-encountered - */ - protected abstract void encounterVertexAgain(V vertex, E edge); - - /** - * Stores iterator-dependent data for a vertex that has been seen. - * - * @param vertex a vertex which has been seen. - * @param data data to be associated with the seen vertex. - * - * @return previous value associated with specified vertex or - * null if no data was associated with the vertex. A - * null return can also indicate that the vertex was explicitly - * associated with null. - */ - protected D putSeenData(V vertex, D data) - { - return seen.put(vertex, data); - } - - /** - * Called when a vertex has been finished (meaning is dependent on traversal - * represented by subclass). - * - * @param vertex vertex which has been finished - */ - protected void finishVertex(V vertex) - { - if (nListeners != 0) { - fireVertexFinished(createVertexTraversalEvent(vertex)); - } - } - - // ------------------------------------------------------------------------- - /** - * @param - * @param - * @param g - * - * @return TODO Document me - */ - static Specifics createGraphSpecifics(Graph g) - { - if (g instanceof DirectedGraph) { - return new DirectedSpecifics((DirectedGraph) g); - } else { - return new UndirectedSpecifics(g); - } - } - - private void addUnseenChildrenOf(V vertex) - { - for (E edge : specifics.edgesOf(vertex)) { - if (nListeners != 0) { - fireEdgeTraversed(createEdgeTraversalEvent(edge)); - } - - V oppositeV = Graphs.getOppositeVertex(graph, edge, vertex); - - if (isSeenVertex(oppositeV)) { - encounterVertexAgain(oppositeV, edge); - } else { - encounterVertex(oppositeV, edge); - } - } - } - - private EdgeTraversalEvent createEdgeTraversalEvent(E edge) - { - if (isReuseEvents()) { - reusableEdgeEvent.setEdge(edge); - - return reusableEdgeEvent; - } else { - return new EdgeTraversalEvent(this, edge); - } - } - - private VertexTraversalEvent createVertexTraversalEvent(V vertex) - { - if (isReuseEvents()) { - reusableVertexEvent.setVertex(vertex); - - return reusableVertexEvent; - } else { - return new VertexTraversalEvent(this, vertex); - } - } - - private void encounterStartVertex() - { - encounterVertex(startVertex, null); - startVertex = null; - } - - //~ Inner Interfaces ------------------------------------------------------- - - static interface SimpleContainer - { - /** - * Tests if this container is empty. - * - * @return true if empty, otherwise false. - */ - public boolean isEmpty(); - - /** - * Adds the specified object to this container. - * - * @param o the object to be added. - */ - public void add(T o); - - /** - * Remove an object from this container and return it. - * - * @return the object removed from this container. - */ - public T remove(); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Provides unified interface for operations that are different in directed - * graphs and in undirected graphs. - */ - abstract static class Specifics - { - /** - * Returns the edges outgoing from the specified vertex in case of - * directed graph, and the edge touching the specified vertex in case of - * undirected graph. - * - * @param vertex the vertex whose outgoing edges are to be returned. - * - * @return the edges outgoing from the specified vertex in case of - * directed graph, and the edge touching the specified vertex in case of - * undirected graph. - */ - public abstract Set edgesOf(VV vertex); - } - - /** - * A reusable edge event. - * - * @author Barak Naveh - * @since Aug 11, 2003 - */ - static class FlyweightEdgeEvent - extends EdgeTraversalEvent - { - private static final long serialVersionUID = 4051327833765000755L; - - /** - * @see EdgeTraversalEvent#EdgeTraversalEvent(Object, Edge) - */ - public FlyweightEdgeEvent(Object eventSource, localE edge) - { - super(eventSource, edge); - } - - /** - * Sets the edge of this event. - * - * @param edge the edge to be set. - */ - protected void setEdge(localE edge) - { - this.edge = edge; - } - } - - /** - * A reusable vertex event. - * - * @author Barak Naveh - * @since Aug 11, 2003 - */ - static class FlyweightVertexEvent - extends VertexTraversalEvent - { - private static final long serialVersionUID = 3834024753848399924L; - - /** - * @see VertexTraversalEvent#VertexTraversalEvent(Object, Object) - */ - public FlyweightVertexEvent(Object eventSource, VV vertex) - { - super(eventSource, vertex); - } - - /** - * Sets the vertex of this event. - * - * @param vertex the vertex to be set. - */ - protected void setVertex(VV vertex) - { - this.vertex = vertex; - } - } - - /** - * An implementation of {@link Specifics} for a directed graph. - */ - private static class DirectedSpecifics - extends Specifics - { - private DirectedGraph graph; - - /** - * Creates a new DirectedSpecifics object. - * - * @param g the graph for which this specifics object to be created. - */ - public DirectedSpecifics(DirectedGraph g) - { - graph = g; - } - - /** - * @see CrossComponentIterator.Specifics#edgesOf(Object) - */ - public Set edgesOf(VV vertex) - { - return graph.outgoingEdgesOf(vertex); - } - } - - /** - * An implementation of {@link Specifics} in which edge direction (if any) - * is ignored. - */ - private static class UndirectedSpecifics - extends Specifics - { - private Graph graph; - - /** - * Creates a new UndirectedSpecifics object. - * - * @param g the graph for which this specifics object to be created. - */ - public UndirectedSpecifics(Graph g) - { - graph = g; - } - - /** - * @see CrossComponentIterator.Specifics#edgesOf(Object) - */ - public Set edgesOf(VV vertex) - { - return graph.edgesOf(vertex); - } - } -} - -// End CrossComponentIterator.java diff --git a/src/org/jgrapht/traverse/DepthFirstIterator.java b/src/org/jgrapht/traverse/DepthFirstIterator.java deleted file mode 100644 index fec48e9..0000000 --- a/src/org/jgrapht/traverse/DepthFirstIterator.java +++ /dev/null @@ -1,223 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------- - * DepthFirstIterator.java - * ----------------------- - * (C) Copyright 2003-2008, by Liviu Rau and Contributors. - * - * Original Author: Liviu Rau - * Contributor(s): Barak Naveh - * Christian Hammer - * Welson Sun - * Ross Judson - * - * $Id$ - * - * Changes - * ------- - * 29-Jul-2003 : Initial revision (LR); - * 31-Jul-2003 : Fixed traversal across connected components (BN); - * 06-Aug-2003 : Extracted common logic to TraverseUtils.XXFirstIterator (BN); - * 31-Jan-2004 : Reparented and changed interface to parent class (BN); - * 04-May-2004 : Made generic (CH) - * 27-Aug-2006 : Added WHITE/GRAY/BLACK to fix bug reported by Welson Sun (JVS) - * 28-Sep-2008 : Optimized using ArrayDeque per suggestion from Ross (JVS) - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * A depth-first iterator for a directed and an undirected graph. For this - * iterator to work correctly the graph must not be modified during iteration. - * Currently there are no means to ensure that, nor to fail-fast. The results of - * such modifications are undefined. - * - * @author Liviu Rau - * @author Barak Naveh - * @since Jul 29, 2003 - */ -public class DepthFirstIterator - extends CrossComponentIterator -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Sentinel object. Unfortunately, we can't use null, because ArrayDeque - * won't accept those. And we don't want to rely on the caller to provide a - * sentinel object for us. So we have to play typecasting games. - */ - public static final Object SENTINEL = new Object(); - - //~ Instance fields -------------------------------------------------------- - - /** - * @see #getStack - */ - private Deque stack = new ArrayDeque(); - - private transient TypeUtil vertexTypeDecl = null; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new depth-first iterator for the specified graph. - * - * @param g the graph to be iterated. - */ - public DepthFirstIterator(Graph g) - { - this(g, null); - } - - /** - * Creates a new depth-first iterator for the specified graph. Iteration - * will start at the specified start vertex and will be limited to the - * connected component that includes that vertex. If the specified start - * vertex is null, iteration will start at an arbitrary vertex - * and will not be limited, that is, will be able to traverse all the graph. - * - * @param g the graph to be iterated. - * @param startVertex the vertex iteration to be started. - */ - public DepthFirstIterator(Graph g, V startVertex) - { - super(g, startVertex); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see CrossComponentIterator#isConnectedComponentExhausted() - */ - protected boolean isConnectedComponentExhausted() - { - for (;;) { - if (stack.isEmpty()) { - return true; - } - if (stack.getLast() != SENTINEL) { - // Found a non-sentinel. - return false; - } - - // Found a sentinel: pop it, record the finish time, - // and then loop to check the rest of the stack. - - // Pop null we peeked at above. - stack.removeLast(); - - // This will pop corresponding vertex to be recorded as finished. - recordFinish(); - } - } - - /** - * @see CrossComponentIterator#encounterVertex(Object, Object) - */ - protected void encounterVertex(V vertex, E edge) - { - putSeenData(vertex, VisitColor.WHITE); - stack.addLast(vertex); - } - - /** - * @see CrossComponentIterator#encounterVertexAgain(Object, Object) - */ - protected void encounterVertexAgain(V vertex, E edge) - { - VisitColor color = getSeenData(vertex); - if (color != VisitColor.WHITE) { - // We've already visited this vertex; no need to mess with the - // stack (either it's BLACK and not there at all, or it's GRAY - // and therefore just a sentinel). - return; - } - - // Since we've encountered it before, and it's still WHITE, it - // *must* be on the stack. Use removeLastOccurrence on the - // assumption that for typical topologies and traversals, - // it's likely to be nearer the top of the stack than - // the bottom of the stack. - boolean found = stack.removeLastOccurrence(vertex); - assert (found); - stack.addLast(vertex); - } - - /** - * @see CrossComponentIterator#provideNextVertex() - */ - protected V provideNextVertex() - { - V v; - for (;;) { - Object o = stack.removeLast(); - if (o == SENTINEL) { - // This is a finish-time sentinel we previously pushed. - recordFinish(); - // Now carry on with another pop until we find a non-sentinel - } else { - // Got a real vertex to start working on - v = TypeUtil.uncheckedCast(o, vertexTypeDecl); - break; - } - } - - // Push a sentinel for v onto the stack so that we'll know - // when we're done with it. - stack.addLast(v); - stack.addLast(SENTINEL); - putSeenData(v, VisitColor.GRAY); - return v; - } - - private void recordFinish() - { - V v = TypeUtil.uncheckedCast(stack.removeLast(), vertexTypeDecl); - putSeenData(v, VisitColor.BLACK); - finishVertex(v); - } - - /** - * Retrieves the LIFO stack of vertices which have been encountered but not - * yet visited (WHITE). This stack also contains sentinel entries - * representing vertices which have been visited but are still GRAY. A - * sentinel entry is a sequence (v, SENTINEL), whereas a non-sentinel entry - * is just (v). - * - * @return stack - */ - public Deque getStack() - { - return stack; - } -} - -// End DepthFirstIterator.java diff --git a/src/org/jgrapht/traverse/GraphIterator.java b/src/org/jgrapht/traverse/GraphIterator.java deleted file mode 100644 index 2cfa98f..0000000 --- a/src/org/jgrapht/traverse/GraphIterator.java +++ /dev/null @@ -1,114 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * GraphIterator.java - * ------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 31-Jul-2003 : Initial revision (BN); - * 11-Aug-2003 : Adaptation to new event model (BN); - * 04-May-2004 : Made generic (CH) - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.event.*; - - -/** - * A graph iterator. - * - * @author Barak Naveh - * @since Jul 31, 2003 - */ -public interface GraphIterator - extends Iterator -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Test whether this iterator is set to traverse the grpah across connected - * components. - * - * @return true if traverses across connected components, - * otherwise false. - */ - public boolean isCrossComponentTraversal(); - - /** - * Sets a value the reuseEvents flag. If the - * reuseEvents flag is set to true this class will reuse - * previously fired events and will not create a new object for each event. - * This option increases performance but should be used with care, - * especially in multithreaded environment. - * - * @param reuseEvents whether to reuse previously fired event objects - * instead of creating a new event object for each event. - */ - public void setReuseEvents(boolean reuseEvents); - - /** - * Tests whether the reuseEvents flag is set. If the flag is - * set to true this class will reuse previously fired events - * and will not create a new object for each event. This option increases - * performance but should be used with care, especially in multithreaded - * environment. - * - * @return the value of the reuseEvents flag. - */ - public boolean isReuseEvents(); - - /** - * Adds the specified traversal listener to this iterator. - * - * @param l the traversal listener to be added. - */ - public void addTraversalListener(TraversalListener l); - - /** - * Unsupported. - * - * @throws UnsupportedOperationException - */ - public void remove(); - - /** - * Removes the specified traversal listener from this iterator. - * - * @param l the traversal listener to be removed. - */ - public void removeTraversalListener(TraversalListener l); -} - -// End GraphIterator.java diff --git a/src/org/jgrapht/traverse/TopologicalOrderIterator.java b/src/org/jgrapht/traverse/TopologicalOrderIterator.java deleted file mode 100644 index 4365373..0000000 --- a/src/org/jgrapht/traverse/TopologicalOrderIterator.java +++ /dev/null @@ -1,277 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------------------- - * TopologicalOrderIterator.java - * ----------------------------- - * (C) Copyright 2004-2008, by Marden Neubert and Contributors. - * - * Original Author: Marden Neubert - * Contributor(s): Barak Naveh, John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 17-Dec-2004 : Initial revision (MN); - * 25-Apr-2005 : Fixes for start vertex order (JVS); - * 06-Jun-2005 : Made generic (CH); - * - */ -package org.jgrapht.traverse; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.util.*; - - -/** - * Implements topological order traversal for a directed acyclic graph. A - * topological sort is a permutation p of the vertices of a graph such - * that an edge (i,j) implies that i appears before j - * in p (Skiena 1990, p. 208). See also - * http://mathworld.wolfram.com/TopologicalSort.html. - * - *

      See "Algorithms in Java, Third Edition, Part 5: Graph Algorithms" by - * Robert Sedgewick and "Data Structures and Algorithms with Object-Oriented - * Design Patterns in Java" by Bruno R. Preiss for implementation alternatives. - * The latter can be found online at - * http://www.brpreiss.com/books/opus5/

      - * - *

      For this iterator to work correctly the graph must be acyclic, and must - * not be modified during iteration. Currently there are no means to ensure - * that, nor to fail-fast; the results with cyclic input (including self-loops) - * or concurrent modifications are undefined. To precheck a graph for cycles, - * consider using {@link org.jgrapht.alg.CycleDetector} or {@link - * org.jgrapht.alg.StrongConnectivityInspector}.

      - * - * @author Marden Neubert - * @since Dec 18, 2004 - */ -public class TopologicalOrderIterator - extends CrossComponentIterator -{ - //~ Instance fields -------------------------------------------------------- - - private Queue queue; - private Map inDegreeMap; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new topological order iterator over the directed graph - * specified, with arbitrary tie-breaking in case of partial order. - * Traversal will start at one of the graph's sources. See the - * definition of source at - * http://mathworld.wolfram.com/Source.html. - * - * @param dg the directed graph to be iterated. - */ - public TopologicalOrderIterator(DirectedGraph dg) - { - this(dg, new LinkedListQueue()); - } - - /** - * Creates a new topological order iterator over the directed graph - * specified, with a user-supplied queue implementation to allow customized - * control over tie-breaking in case of partial order. Traversal will start - * at one of the graph's sources. See the definition of source at - * http://mathworld.wolfram.com/Source.html. - * - * @param dg the directed graph to be iterated. - * @param queue queue to use for tie-break in case of partial order (e.g. a - * PriorityQueue can be used to break ties according to vertex priority); - * must be initially empty - */ - public TopologicalOrderIterator(DirectedGraph dg, Queue queue) - { - this(dg, queue, new HashMap()); - } - - // NOTE: This is a hack to deal with the fact that CrossComponentIterator - // needs to know the start vertex in its constructor - private TopologicalOrderIterator( - DirectedGraph dg, - Queue queue, - Map inDegreeMap) - { - this(dg, initialize(dg, queue, inDegreeMap)); - this.queue = queue; - this.inDegreeMap = inDegreeMap; - - // empty queue for non-empty graph would indicate presence of - // cycles (no roots found) - assert dg.vertexSet().isEmpty() || !queue.isEmpty(); - } - - // NOTE: This is intentionally private, because starting the sort "in the - // middle" doesn't make sense. - private TopologicalOrderIterator(DirectedGraph dg, V start) - { - super(dg, start); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @see CrossComponentIterator#isConnectedComponentExhausted() - */ - protected boolean isConnectedComponentExhausted() - { - // FIXME jvs 25-Apr-2005: This isn't correct for a graph with more than - // one component. We will actually exhaust a connected component - // before the queue is empty, because initialize adds roots from all - // components to the queue. - return queue.isEmpty(); - } - - /** - * @see CrossComponentIterator#encounterVertex(Object, Object) - */ - protected void encounterVertex(V vertex, E edge) - { - putSeenData(vertex, null); - decrementInDegree(vertex); - } - - /** - * @see CrossComponentIterator#encounterVertexAgain(Object, Object) - */ - protected void encounterVertexAgain(V vertex, E edge) - { - decrementInDegree(vertex); - } - - /** - * @see CrossComponentIterator#provideNextVertex() - */ - protected V provideNextVertex() - { - return queue.remove(); - } - - /** - * Decrements the in-degree of a vertex. - * - * @param vertex the vertex whose in-degree will be decremented. - */ - private void decrementInDegree(V vertex) - { - ModifiableInteger inDegree = inDegreeMap.get(vertex); - - if (inDegree.value > 0) { - inDegree.value--; - - if (inDegree.value == 0) { - queue.offer(vertex); - } - } - } - - /** - * Initializes the internal traversal object structure. Sets up the internal - * queue with the directed graph vertices and creates the control structure - * for the in-degrees. - * - * @param dg the directed graph to be iterated. - * @param queue initializer for queue - * @param inDegreeMap initializer for inDegreeMap - * - * @return start vertex - */ - private static V initialize( - DirectedGraph dg, - Queue queue, - Map inDegreeMap) - { - for (Iterator i = dg.vertexSet().iterator(); i.hasNext();) { - V vertex = i.next(); - - int inDegree = dg.inDegreeOf(vertex); - inDegreeMap.put(vertex, new ModifiableInteger(inDegree)); - - if (inDegree == 0) { - queue.offer(vertex); - } - } - - if (queue.isEmpty()) { - return null; - } else { - return queue.peek(); - } - } - - //~ Inner Classes ---------------------------------------------------------- - - // NOTE jvs 22-Dec-2006: For JDK1.4-compatibility, we can't assume - // that LinkedList implements Queue, since that wasn't introduced - // until JDK1.5, so use an adapter here. Move this to - // top-level in org.jgrapht.util if anyone else needs it. - private static class LinkedListQueue - extends LinkedList - implements Queue - { - private static final long serialVersionUID = 4217659843476891334L; - - public T element() - { - return getFirst(); - } - - public boolean offer(T o) - { - return add(o); - } - - public T peek() - { - if (isEmpty()) { - return null; - } - return getFirst(); - } - - public T poll() - { - if (isEmpty()) { - return null; - } - return removeFirst(); - } - - public T remove() - { - return removeFirst(); - } - } -} - -// End TopologicalOrderIterator.java diff --git a/src/org/jgrapht/traverse/package.html b/src/org/jgrapht/traverse/package.html deleted file mode 100644 index 145444a..0000000 --- a/src/org/jgrapht/traverse/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Graph traversal means. - - \ No newline at end of file diff --git a/src/org/jgrapht/util/ArrayUnenforcedSet.java b/src/org/jgrapht/util/ArrayUnenforcedSet.java deleted file mode 100644 index b9387fe..0000000 --- a/src/org/jgrapht/util/ArrayUnenforcedSet.java +++ /dev/null @@ -1,112 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * ArrayUnenforcedSet.java - * ----------------- - * (C) Copyright 2006-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 07-May-2006 : Initial version (JVS); - */ -package org.jgrapht.util; - -import java.util.*; - - -/** - * Helper for efficiently representing small sets whose elements are known to be - * unique by construction, implying we don't need to enforce the uniqueness - * property in the data structure itself. Use with caution. - * - *

      Note that for equals/hashCode, the class implements the Set behavior - * (unordered), not the list behavior (ordered); the fact that it subclasses - * ArrayList should be considered an implementation detail. - * - * @author John V. Sichi - */ -public class ArrayUnenforcedSet - extends ArrayList - implements Set -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = -7413250161201811238L; - - //~ Constructors ----------------------------------------------------------- - - public ArrayUnenforcedSet() - { - super(); - } - - public ArrayUnenforcedSet(Collection c) - { - super(c); - } - - public ArrayUnenforcedSet(int n) - { - super(n); - } - - //~ Methods ---------------------------------------------------------------- - - public boolean equals(Object o) - { - return new SetForEquality().equals(o); - } - - public int hashCode() - { - return new SetForEquality().hashCode(); - } - - //~ Inner Classes ---------------------------------------------------------- - - /** - * Multiple inheritance helper. - */ - private class SetForEquality - extends AbstractSet - { - public Iterator iterator() - { - return ArrayUnenforcedSet.this.iterator(); - } - - public int size() - { - return ArrayUnenforcedSet.this.size(); - } - } -} - -// End ArrayUnenforcedSet.java diff --git a/src/org/jgrapht/util/FibonacciHeap.java b/src/org/jgrapht/util/FibonacciHeap.java deleted file mode 100644 index 569ed8c..0000000 --- a/src/org/jgrapht/util/FibonacciHeap.java +++ /dev/null @@ -1,611 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * FibonnaciHeap.java - * -------------------------- - * (C) Copyright 1999-2003, by Nathan Fiedler and Contributors. - * - * Original Author: Nathan Fiedler - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS); - * - * Name Date Description - * ---- ---- ----------- - * nf 08/31/97 Initial version - * nf 09/07/97 Removed FibHeapData interface - * nf 01/20/01 Added synchronization - * nf 01/21/01 Made Node an inner class - * nf 01/05/02 Added clear(), renamed empty() to - * isEmpty(), and renamed printHeap() - * to toString() - * nf 01/06/02 Removed all synchronization - * - */ -package org.jgrapht.util; - -import java.util.*; - - -/** - * This class implements a Fibonacci heap data structure. Much of the code in - * this class is based on the algorithms in the "Introduction to Algorithms"by - * Cormen, Leiserson, and Rivest in Chapter 21. The amortized running time of - * most of these methods is O(1), making it a very fast data structure. Several - * have an actual running time of O(1). removeMin() and delete() have O(log n) - * amortized running times because they do the heap consolidation. If you - * attempt to store nodes in this heap with key values of -Infinity - * (Double.NEGATIVE_INFINITY) the delete() operation may fail to - * remove the correct element. - * - *

      Note that this implementation is not synchronized. If multiple - * threads access a set concurrently, and at least one of the threads modifies - * the set, it must be synchronized externally. This is typically - * accomplished by synchronizing on some object that naturally encapsulates the - * set.

      - * - *

      This class was originally developed by Nathan Fiedler for the GraphMaker - * project. It was imported to JGraphT with permission, courtesy of Nathan - * Fiedler.

      - * - * @author Nathan Fiedler - */ -public class FibonacciHeap -{ - //~ Static fields/initializers --------------------------------------------- - - private static final double oneOverLogPhi = - 1.0 / Math.log((1.0 + Math.sqrt(5.0)) / 2.0); - - //~ Instance fields -------------------------------------------------------- - - /** - * Points to the minimum node in the heap. - */ - private FibonacciHeapNode minNode; - - /** - * Number of nodes in the heap. - */ - private int nNodes; - - //~ Constructors ----------------------------------------------------------- - - /** - * Constructs a FibonacciHeap object that contains no elements. - */ - public FibonacciHeap() - { - } // FibonacciHeap - - //~ Methods ---------------------------------------------------------------- - - /** - * Tests if the Fibonacci heap is empty or not. Returns true if the heap is - * empty, false otherwise. - * - *

      Running time: O(1) actual

      - * - * @return true if the heap is empty, false otherwise - */ - public boolean isEmpty() - { - return minNode == null; - } - - // isEmpty - - /** - * Removes all elements from this heap. - */ - public void clear() - { - minNode = null; - nNodes = 0; - } - - // clear - - /** - * Decreases the key value for a heap node, given the new value to take on. - * The structure of the heap may be changed and will not be consolidated. - * - *

      Running time: O(1) amortized

      - * - * @param x node to decrease the key of - * @param k new key value for node x - * - * @exception IllegalArgumentException Thrown if k is larger than x.key - * value. - */ - public void decreaseKey(FibonacciHeapNode x, double k) - { - if (k > x.key) { - throw new IllegalArgumentException( - "decreaseKey() got larger key value"); - } - - x.key = k; - - FibonacciHeapNode y = x.parent; - - if ((y != null) && (x.key < y.key)) { - cut(x, y); - cascadingCut(y); - } - - if (x.key < minNode.key) { - minNode = x; - } - } - - // decreaseKey - - /** - * Deletes a node from the heap given the reference to the node. The trees - * in the heap will be consolidated, if necessary. This operation may fail - * to remove the correct element if there are nodes with key value - * -Infinity. - * - *

      Running time: O(log n) amortized

      - * - * @param x node to remove from heap - */ - public void delete(FibonacciHeapNode x) - { - // make x as small as possible - decreaseKey(x, Double.NEGATIVE_INFINITY); - - // remove the smallest, which decreases n also - removeMin(); - } - - // delete - - /** - * Inserts a new data element into the heap. No heap consolidation is - * performed at this time, the new node is simply inserted into the root - * list of this heap. - * - *

      Running time: O(1) actual

      - * - * @param node new node to insert into heap - * @param key key value associated with data object - */ - public void insert(FibonacciHeapNode node, double key) - { - node.key = key; - - // concatenate node into min list - if (minNode != null) { - node.left = minNode; - node.right = minNode.right; - minNode.right = node; - node.right.left = node; - - if (key < minNode.key) { - minNode = node; - } - } else { - minNode = node; - } - - nNodes++; - } - - // insert - - /** - * Returns the smallest element in the heap. This smallest element is the - * one with the minimum key value. - * - *

      Running time: O(1) actual

      - * - * @return heap node with the smallest key - */ - public FibonacciHeapNode min() - { - return minNode; - } - - // min - - /** - * Removes the smallest element from the heap. This will cause the trees in - * the heap to be consolidated, if necessary. - * - *

      Running time: O(log n) amortized

      - * - * @return node with the smallest key - */ - public FibonacciHeapNode removeMin() - { - FibonacciHeapNode z = minNode; - - if (z != null) { - int numKids = z.degree; - FibonacciHeapNode x = z.child; - FibonacciHeapNode tempRight; - - // for each child of z do... - while (numKids > 0) { - tempRight = x.right; - - // remove x from child list - x.left.right = x.right; - x.right.left = x.left; - - // add x to root list of heap - x.left = minNode; - x.right = minNode.right; - minNode.right = x; - x.right.left = x; - - // set parent[x] to null - x.parent = null; - x = tempRight; - numKids--; - } - - // remove z from root list of heap - z.left.right = z.right; - z.right.left = z.left; - - if (z == z.right) { - minNode = null; - } else { - minNode = z.right; - consolidate(); - } - - // decrement size of heap - nNodes--; - } - - return z; - } - - // removeMin - - /** - * Returns the size of the heap which is measured in the number of elements - * contained in the heap. - * - *

      Running time: O(1) actual

      - * - * @return number of elements in the heap - */ - public int size() - { - return nNodes; - } - - // size - - /** - * Joins two Fibonacci heaps into a new one. No heap consolidation is - * performed at this time. The two root lists are simply joined together. - * - *

      Running time: O(1) actual

      - * - * @param h1 first heap - * @param h2 second heap - * - * @return new heap containing h1 and h2 - */ - public static FibonacciHeap union( - FibonacciHeap h1, - FibonacciHeap h2) - { - FibonacciHeap h = new FibonacciHeap(); - - if ((h1 != null) && (h2 != null)) { - h.minNode = h1.minNode; - - if (h.minNode != null) { - if (h2.minNode != null) { - h.minNode.right.left = h2.minNode.left; - h2.minNode.left.right = h.minNode.right; - h.minNode.right = h2.minNode; - h2.minNode.left = h.minNode; - - if (h2.minNode.key < h1.minNode.key) { - h.minNode = h2.minNode; - } - } - } else { - h.minNode = h2.minNode; - } - - h.nNodes = h1.nNodes + h2.nNodes; - } - - return h; - } - - // union - - /** - * Creates a String representation of this Fibonacci heap. - * - * @return String of this. - */ - public String toString() - { - if (minNode == null) { - return "FibonacciHeap=[]"; - } - - // create a new stack and put root on it - Stack> stack = new Stack>(); - stack.push(minNode); - - StringBuffer buf = new StringBuffer(512); - buf.append("FibonacciHeap=["); - - // do a simple breadth-first traversal on the tree - while (!stack.empty()) { - FibonacciHeapNode curr = stack.pop(); - buf.append(curr); - buf.append(", "); - - if (curr.child != null) { - stack.push(curr.child); - } - - FibonacciHeapNode start = curr; - curr = curr.right; - - while (curr != start) { - buf.append(curr); - buf.append(", "); - - if (curr.child != null) { - stack.push(curr.child); - } - - curr = curr.right; - } - } - - buf.append(']'); - - return buf.toString(); - } - - // toString - - /** - * Performs a cascading cut operation. This cuts y from its parent and then - * does the same for its parent, and so on up the tree. - * - *

      Running time: O(log n); O(1) excluding the recursion

      - * - * @param y node to perform cascading cut on - */ - protected void cascadingCut(FibonacciHeapNode y) - { - FibonacciHeapNode z = y.parent; - - // if there's a parent... - if (z != null) { - // if y is unmarked, set it marked - if (!y.mark) { - y.mark = true; - } else { - // it's marked, cut it from parent - cut(y, z); - - // cut its parent as well - cascadingCut(z); - } - } - } - - // cascadingCut - - protected void consolidate() - { - int arraySize = - ((int) Math.floor(Math.log(nNodes) * oneOverLogPhi)) + 1; - - List> array = - new ArrayList>(arraySize); - - // Initialize degree array - for (int i = 0; i < arraySize; i++) { - array.add(null); - } - - // Find the number of root nodes. - int numRoots = 0; - FibonacciHeapNode x = minNode; - - if (x != null) { - numRoots++; - x = x.right; - - while (x != minNode) { - numRoots++; - x = x.right; - } - } - - // For each node in root list do... - while (numRoots > 0) { - // Access this node's degree.. - int d = x.degree; - FibonacciHeapNode next = x.right; - - // ..and see if there's another of the same degree. - for (;;) { - FibonacciHeapNode y = array.get(d); - if (y == null) { - // Nope. - break; - } - - // There is, make one of the nodes a child of the other. - // Do this based on the key value. - if (x.key > y.key) { - FibonacciHeapNode temp = y; - y = x; - x = temp; - } - - // FibonacciHeapNode y disappears from root list. - link(y, x); - - // We've handled this degree, go to next one. - array.set(d, null); - d++; - } - - // Save this node for later when we might encounter another - // of the same degree. - array.set(d, x); - - // Move forward through list. - x = next; - numRoots--; - } - - // Set min to null (effectively losing the root list) and - // reconstruct the root list from the array entries in array[]. - minNode = null; - - for (int i = 0; i < arraySize; i++) { - FibonacciHeapNode y = array.get(i); - if (y == null) { - continue; - } - - // We've got a live one, add it to root list. - if (minNode != null) { - // First remove node from root list. - y.left.right = y.right; - y.right.left = y.left; - - // Now add to root list, again. - y.left = minNode; - y.right = minNode.right; - minNode.right = y; - y.right.left = y; - - // Check if this is a new min. - if (y.key < minNode.key) { - minNode = y; - } - } else { - minNode = y; - } - } - } - - // consolidate - - /** - * The reverse of the link operation: removes x from the child list of y. - * This method assumes that min is non-null. - * - *

      Running time: O(1)

      - * - * @param x child of y to be removed from y's child list - * @param y parent of x about to lose a child - */ - protected void cut(FibonacciHeapNode x, FibonacciHeapNode y) - { - // remove x from childlist of y and decrement degree[y] - x.left.right = x.right; - x.right.left = x.left; - y.degree--; - - // reset y.child if necessary - if (y.child == x) { - y.child = x.right; - } - - if (y.degree == 0) { - y.child = null; - } - - // add x to root list of heap - x.left = minNode; - x.right = minNode.right; - minNode.right = x; - x.right.left = x; - - // set parent[x] to nil - x.parent = null; - - // set mark[x] to false - x.mark = false; - } - - // cut - - /** - * Make node y a child of node x. - * - *

      Running time: O(1) actual

      - * - * @param y node to become child - * @param x node to become parent - */ - protected void link(FibonacciHeapNode y, FibonacciHeapNode x) - { - // remove y from root list of heap - y.left.right = y.right; - y.right.left = y.left; - - // make y a child of x - y.parent = x; - - if (x.child == null) { - x.child = y; - y.right = y; - y.left = y; - } else { - y.left = x.child; - y.right = x.child.right; - x.child.right = y; - y.right.left = y; - } - - // increase degree[x] - x.degree++; - - // set mark[y] false - y.mark = false; - } - - // link -} - -// FibonacciHeap diff --git a/src/org/jgrapht/util/FibonacciHeapNode.java b/src/org/jgrapht/util/FibonacciHeapNode.java deleted file mode 100644 index 2a54150..0000000 --- a/src/org/jgrapht/util/FibonacciHeapNode.java +++ /dev/null @@ -1,154 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (barak_naveh@users.sourceforge.net) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------------- - * FibonnaciHeapNode.java - * -------------------------- - * (C) Copyright 1999-2008, by Nathan Fiedler and Contributors. - * - * Original Author: Nathan Fiedler - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 03-Sept-2003 : Adapted from Nathan Fiedler (JVS); - * - * Name Date Description - * ---- ---- ----------- - * nf 08/31/97 Initial version - * nf 09/07/97 Removed FibHeapData interface - * nf 01/20/01 Added synchronization - * nf 01/21/01 Made Node an inner class - * nf 01/05/02 Added clear(), renamed empty() to - * isEmpty(), and renamed printHeap() - * to toString() - * nf 01/06/02 Removed all synchronization - * JVS 06/24/06 Generics - * - */ -package org.jgrapht.util; - -/** - * Implements a node of the Fibonacci heap. It holds the information necessary - * for maintaining the structure of the heap. It also holds the reference to the - * key value (which is used to determine the heap structure). - * - * @author Nathan Fiedler - */ -public class FibonacciHeapNode -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Node data. - */ - T data; - - /** - * first child node - */ - FibonacciHeapNode child; - - /** - * left sibling node - */ - FibonacciHeapNode left; - - /** - * parent node - */ - FibonacciHeapNode parent; - - /** - * right sibling node - */ - FibonacciHeapNode right; - - /** - * true if this node has had a child removed since this node was added to - * its parent - */ - boolean mark; - - /** - * key value for this node - */ - double key; - - /** - * number of children of this node (does not count grandchildren) - */ - int degree; - - //~ Constructors ----------------------------------------------------------- - - /** - * Default constructor. Initializes the right and left pointers, making this - * a circular doubly-linked list. - * - * @param data data for this node - */ - public FibonacciHeapNode(T data) - { - right = this; - left = this; - this.data = data; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Obtain the key for this node. - * - * @return the key - */ - public final double getKey() - { - return key; - } - - /** - * Obtain the data for this node. - */ - public final T getData() - { - return data; - } - - /** - * Return the string representation of this object. - * - * @return string representing this object - */ - public String toString() - { - return Double.toString(key); - } - - // toString -} - -// End FibonacciHeapNode.java diff --git a/src/org/jgrapht/util/MathUtil.java b/src/org/jgrapht/util/MathUtil.java deleted file mode 100644 index 87620d8..0000000 --- a/src/org/jgrapht/util/MathUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * MathUtil.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.util; - -/** - * Math Utilities. Currently contains the following: - *
    22. factorial(int N) - caclulate the factorial of N (aka N!) - * - * @author Assaf - * @since May 30, 2005 - */ -public class MathUtil -{ - //~ Methods ---------------------------------------------------------------- - - public static long factorial(int N) - { - long multi = 1; - for (int i = 1; i <= N; i++) { - multi = multi * i; - } - return multi; - } -} - -// End MathUtil.java diff --git a/src/org/jgrapht/util/ModifiableInteger.java b/src/org/jgrapht/util/ModifiableInteger.java deleted file mode 100644 index 041c6aa..0000000 --- a/src/org/jgrapht/util/ModifiableInteger.java +++ /dev/null @@ -1,261 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------------- - * ModifiableInteger.java - * ---------------------- - * - * (C) Copyright 2002-2004, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 2004-05-27 : Initial version (BN); - * - */ -package org.jgrapht.util; - -/** - * The ModifiableInteger class wraps a value of the primitive type - * int in an object, similarly to {@link java.lang.Integer}. An - * object of type ModifiableInteger contains a single field whose - * type is int. - * - *

      Unlike java.lang.Integer, the int value which the - * ModifiableInteger represents can be modified. It becomes useful when used - * together with the collection framework. For example, if you want to have a - * {@link java.util.List} of counters. You could use Integer but - * that would have became wasteful and inefficient if you frequently had to - * update the counters.

      - * - *

      WARNING: Because instances of this class are mutable, great care must be - * exercised if used as keys of a {@link java.util.Map} or as values in a {@link - * java.util.Set} in a manner that affects equals comparisons while the - * instances are keys in the map (or values in the set). For more see - * documentation of Map and Set.

      - * - * @author Barak Naveh - * @since May 27, 2004 - */ -public class ModifiableInteger - extends Number - implements Comparable -{ - //~ Static fields/initializers --------------------------------------------- - - private static final long serialVersionUID = 3618698612851422261L; - - //~ Instance fields -------------------------------------------------------- - - /** - * The int value represented by this ModifiableInteger. - */ - public int value; - - //~ Constructors ----------------------------------------------------------- - - /** - * !!! DON'T USE - Use the {@link #ModifiableInteger(int)} constructor - * instead !!! - * - *

      This constructor is for the use of java.beans.XMLDecoder - * deserialization. The constructor is marked as 'deprecated' to indicate to - * the programmer against using it by mistake.

      - * - * @deprecated not really deprecated, just marked so to avoid mistaken use. - */ - @Deprecated public ModifiableInteger() - { - } - - /** - * Constructs a newly allocated ModifiableInteger object that - * represents the specified int value. - * - * @param value the value to be represented by the - * ModifiableInteger object. - */ - public ModifiableInteger(int value) - { - this.value = value; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Sets a new value for this modifiable integer. - * - * @param value the new value to set. - */ - public void setValue(int value) - { - this.value = value; - } - - /** - * Returns the value of this object, similarly to {@link #intValue()}. This - * getter is NOT redundant. It is used for serialization by - * java.beans.XMLEncoder. - * - * @return the value. - */ - public int getValue() - { - return this.value; - } - - /** - * Adds one to the value of this modifiable integer. - */ - public void increment() - { - this.value++; - } - - /** - * Subtracts one from the value of this modifiable integer. - */ - public void decrement() - { - this.value--; - } - - /** - * Compares two ModifiableInteger objects numerically. - * - * @param anotherInteger the ModifiableInteger to be compared. - * - * @return the value 0 if this ModifiableInteger - * is equal to the argument ModifiableInteger; a value less - * than 0 if this ModifiableInteger is numerically - * less than the argument ModifiableInteger; and a value - * greater than 0 if this ModifiableInteger is - * numerically greater than the argument ModifiableInteger - * (signed comparison). - */ - public int compareTo(ModifiableInteger anotherInteger) - { - int thisVal = this.value; - int anotherVal = anotherInteger.value; - - return (thisVal < anotherVal) ? -1 : ((thisVal == anotherVal) ? 0 : 1); - } - - /** - * @see Number#doubleValue() - */ - public double doubleValue() - { - return this.value; - } - - /** - * Compares this object to the specified object. The result is - * true if and only if the argument is not null and is - * an ModifiableInteger object that contains the same - * int value as this object. - * - * @param o the object to compare with. - * - * @return true if the objects are the same; false - * otherwise. - */ - public boolean equals(Object o) - { - if (o instanceof ModifiableInteger) { - return this.value == ((ModifiableInteger) o).value; - } - - return false; - } - - /** - * @see Number#floatValue() - */ - public float floatValue() - { - return this.value; - } - - /** - * Returns a hash code for this ModifiableInteger. - * - * @return a hash code value for this object, equal to the primitive - * int value represented by this ModifiableInteger - * object. - */ - public int hashCode() - { - return this.value; - } - - /** - * @see Number#intValue() - */ - public int intValue() - { - return this.value; - } - - /** - * @see Number#longValue() - */ - public long longValue() - { - return this.value; - } - - /** - * Returns an Integer object representing this - * ModifiableInteger's value. - * - * @return an Integer representation of the value of this - * object. - */ - public Integer toInteger() - { - return Integer.valueOf(this.value); - } - - /** - * Returns a String object representing this - * ModifiableInteger's value. The value is converted to signed - * decimal representation and returned as a string, exactly as if the - * integer value were given as an argument to the {@link - * java.lang.Integer#toString(int)} method. - * - * @return a string representation of the value of this object in - * base 10. - */ - public String toString() - { - return String.valueOf(this.value); - } -} - -// End ModifiableInteger.java diff --git a/src/org/jgrapht/util/PrefetchIterator.java b/src/org/jgrapht/util/PrefetchIterator.java deleted file mode 100644 index e37fde0..0000000 --- a/src/org/jgrapht/util/PrefetchIterator.java +++ /dev/null @@ -1,223 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * PrefetchIterator.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - */ -package org.jgrapht.util; - -import java.util.*; - - -/** - * Utility class to help implement an iterator/enumerator in which the hasNext() - * method needs to calculate the next elements ahead of time. - * - *

      Many classes which implement an iterator face a common problem: if there - * is no easy way to calculate hasNext() other than to call getNext(), then they - * save the result for fetching in the next call to getNext(). This utility - * helps in doing just that. - * - *

      Usage: The new iterator class will hold this class as a member - * variable and forward the hasNext() and next() to it. When creating an - * instance of this class, you supply it with a functor that is doing the real - * job of calculating the next element. - * - *

      
      -    //This class supllies enumeration of integer till 100.
      -    public class IteratorExample implements Enumeration{
      -    private int counter=0;
      -    private PrefetchIterator nextSupplier;
      -
      -        IteratorExample()
      -        {
      -            nextSupplier = new PrefetchIterator(new PrefetchIterator.NextElementFunctor(){
      -
      -                public Object nextElement() throws NoSuchElementException {
      -                    counter++;
      -                    if (counter>=100)
      -                        throw new NoSuchElementException();
      -                    else
      -                        return new Integer(counter);
      -                }
      -
      -            });
      -        }
      -        //forwarding to nextSupplier and return its returned value
      -        public boolean hasMoreElements() {
      -            return this.nextSupplier.hasMoreElements();
      -        }
      -    //  forwarding to nextSupplier and return its returned value
      -        public Object nextElement() {
      -            return this.nextSupplier.nextElement();
      -        }
      -  }
      - * - * - * @author Assaf_Lehr - */ -public class PrefetchIterator - implements Iterator, - Enumeration -{ - //~ Instance fields -------------------------------------------------------- - - private NextElementFunctor innerEnum; - private E getNextLastResult; - private boolean isGetNextLastResultUpToDate = false; - private boolean endOfEnumerationReached = false; - private boolean flagIsEnumerationStartedEmpty = true; - private int innerFunctorUsageCounter = 0; - - //~ Constructors ----------------------------------------------------------- - - public PrefetchIterator(NextElementFunctor aEnum) - { - innerEnum = aEnum; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Serves as one contact place to the functor; all must use it and not - * directly the NextElementFunctor. - */ - private E getNextElementFromInnerFunctor() - { - innerFunctorUsageCounter++; - E result = this.innerEnum.nextElement(); - - // if we got here , an exception was not thrown, so at least - // one time a good value returned - flagIsEnumerationStartedEmpty = false; - return result; - } - - /** - * 1. Retrieves the saved value or calculates it if it does not exist 2. - * Changes isGetNextLastResultUpToDate to false. (Because it does not save - * the NEXT element now; it saves the current one!) - */ - public E nextElement() - { - E result = null; - if (this.isGetNextLastResultUpToDate) { - result = this.getNextLastResult; - } else { - result = getNextElementFromInnerFunctor(); - } - - this.isGetNextLastResultUpToDate = false; - return result; - } - - /** - * If (isGetNextLastResultUpToDate==true) returns true else 1. calculates - * getNext() and saves it 2. sets isGetNextLastResultUpToDate to true. - */ - public boolean hasMoreElements() - { - if (endOfEnumerationReached) { - return false; - } - - if (isGetNextLastResultUpToDate) { - return true; - } else { - try { - this.getNextLastResult = getNextElementFromInnerFunctor(); - this.isGetNextLastResultUpToDate = true; - return true; - } catch (NoSuchElementException noSuchE) { - endOfEnumerationReached = true; - return false; - } - } // else - } // method - - /** - * Tests whether the enumeration started as an empty one. It does not matter - * if it hasMoreElements() now, only at initialization time. Efficiency: if - * nextElements(), hasMoreElements() were never used, it activates the - * hasMoreElements() once. Else it is immediately(O(1)) - */ - public boolean isEnumerationStartedEmpty() - { - if (this.innerFunctorUsageCounter == 0) { - if (hasMoreElements()) { - return false; - } else { - return true; - } - } else // it is not the first time , so use the saved value - // which was initilaizeed during a call to - // getNextElementFromInnerFunctor - { - return flagIsEnumerationStartedEmpty; - } - } - - public boolean hasNext() - { - return this.hasMoreElements(); - } - - public E next() - { - return this.nextElement(); - } - - /** - * Always throws UnsupportedOperationException. - */ - public void remove() - throws UnsupportedOperationException - { - throw new UnsupportedOperationException(); - } - - //~ Inner Interfaces ------------------------------------------------------- - - public interface NextElementFunctor - { - /** - * You must implement that NoSuchElementException is thrown on - * nextElement() if it is out of bound. - */ - public EE nextElement() - throws NoSuchElementException; - } -} - -// End PrefetchIterator.java diff --git a/src/org/jgrapht/util/TypeUtil.java b/src/org/jgrapht/util/TypeUtil.java deleted file mode 100644 index 81f2937..0000000 --- a/src/org/jgrapht/util/TypeUtil.java +++ /dev/null @@ -1,67 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * TypeUtil.java - * ----------------- - * (C) Copyright 2006-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 07-May-2006 : Initial version (JVS); - */ -package org.jgrapht.util; - -/** - * TypeUtil isolates type-unsafety so that code which uses it for legitimate - * reasons can stay warning-free. - * - * @author John V. Sichi - */ -public class TypeUtil -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Casts an object to a type. - * - * @param o object to be cast - * @param typeDecl conveys the target type information; the actual value is - * unused and can be null since this is all just stupid compiler tricks - * - * @return the result of the cast - */ - @SuppressWarnings("unchecked") - public static T uncheckedCast(Object o, TypeUtil typeDecl) - { - return (T) o; - } -} - -// End TypeUtil.java diff --git a/src/org/jgrapht/util/VertexPair.java b/src/org/jgrapht/util/VertexPair.java deleted file mode 100644 index 5dc1c5a..0000000 --- a/src/org/jgrapht/util/VertexPair.java +++ /dev/null @@ -1,132 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * VertexPair.java - * ------------------------- - * (C) Copyright 2009-2009, by Soren Davidsen and Contributors - * - * Original Author: Soren Davidsen - * - * $Id$ - * - * Changes - * ------- - * 03-Dec-2009 : Initial revision (SD); - * - */ -package org.jgrapht.util; - -/** - * Representation of a pair of vertices; to be replaced by Pair if Sun ever - * gets around to adding Pair to java.util. - * - * @author Soren - */ -public class VertexPair -{ - //~ Instance fields -------------------------------------------------------- - - private V n1; - private V n2; - - //~ Constructors ----------------------------------------------------------- - - public VertexPair(V n1, V n2) - { - this.n1 = n1; - this.n2 = n2; - } - - //~ Methods ---------------------------------------------------------------- - - public V getFirst() - { - return n1; - } - - public V getSecond() - { - return n2; - } - - /** - * Assess if this pair contains the vertex. - * - * @param v The vertex in question - * - * @return true if contains, false otherwise - */ - public boolean hasVertex(V v) - { - return v.equals(n1) || v.equals(n2); - } - - public V getOther(V one) - { - if (one.equals(n1)) { - return n2; - } else if (one.equals(n2)) { - return n1; - } else { - return null; - } - } - - @Override public String toString() - { - return n1 + "," + n2; - } - - @Override public boolean equals(Object o) - { - if (this == o) { - return true; - } - if ((o == null) || (getClass() != o.getClass())) { - return false; - } - - @SuppressWarnings("unchecked") - VertexPair that = (VertexPair) o; - - if ((n1 != null) ? (!n1.equals(that.n1)) : (that.n1 != null)) { - return false; - } - if ((n2 != null) ? (!n2.equals(that.n2)) : (that.n2 != null)) { - return false; - } - - return true; - } - - @Override public int hashCode() - { - int result = (n1 != null) ? n1.hashCode() : 0; - result = (31 * result) + ((n2 != null) ? n2.hashCode() : 0); - return result; - } -} - -// End VertexPair.java diff --git a/src/org/jgrapht/util/WeightCombiner.java b/src/org/jgrapht/util/WeightCombiner.java deleted file mode 100644 index 637dd18..0000000 --- a/src/org/jgrapht/util/WeightCombiner.java +++ /dev/null @@ -1,116 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2009, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * WeightCombiner.java - * ------------------------- - * (C) Copyright 2009-2009, by Ilya Razenshteyn - * - * Original Author: Ilya Razenshteyn and Contributors. - * - * $Id$ - * - * Changes - * ------- - * 02-Feb-2009 : Initial revision (IR); - * - */ -package org.jgrapht.util; - -/** - * Binary operator for edge weights. There are some prewritten operators. - */ -public interface WeightCombiner -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Sum of weights. - */ - public WeightCombiner SUM = - new WeightCombiner() { - public double combine(double a, double b) - { - return a + b; - } - }; - - /** - * Minimum weight. - */ - public WeightCombiner MIN = - new WeightCombiner() { - public double combine(double a, double b) - { - return Math.min(a, b); - } - }; - - /** - * Maximum weight. - */ - public WeightCombiner MAX = - new WeightCombiner() { - public double combine(double a, double b) - { - return Math.max(a, b); - } - }; - - /** - * First weight. - */ - public WeightCombiner FIRST = - new WeightCombiner() { - public double combine(double a, double b) - { - return a; - } - }; - - /** - * Second weight. - */ - public WeightCombiner SECOND = - new WeightCombiner() { - public double combine(double a, double b) - { - return b; - } - }; - - //~ Methods ---------------------------------------------------------------- - - /** - * Combines two weights. - * - * @param a first weight - * @param b second weight - * - * @return result of the operator - */ - double combine(double a, double b); -} - -// End WeightCombiner.java diff --git a/src/org/jgrapht/util/package.html b/src/org/jgrapht/util/package.html deleted file mode 100644 index 15706d5..0000000 --- a/src/org/jgrapht/util/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - -Non-graph-specific data structures, algorithms, and utilities used by -JGraphT. - - From 1444901b8fe877aa0d356244db3692e7b6e7ca57 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 21 Sep 2012 16:43:57 -0400 Subject: [PATCH 089/140] Removing jgrapht but keepign interfaces --- .../compositetask/CompositeTask.java | 1 - .../compositetask/CompositeTaskEdgeFactory.java | 2 - .../compositetask/CompositeTaskGraph.java | 2 - .../compositetask}/DirectedGraph.java | 4 +- .../compositetask}/EdgeFactory.java | 3 +- .../compositetask}/Graph.java | 4 +- src/org/jgrapht/GraphHelper.java | 59 --- src/org/jgrapht/GraphMapping.java | 75 ---- src/org/jgrapht/GraphPath.java | 105 ----- src/org/jgrapht/Graphs.java | 442 --------------------- src/org/jgrapht/ListenableGraph.java | 90 ----- src/org/jgrapht/UndirectedGraph.java | 70 ---- src/org/jgrapht/VertexFactory.java | 63 --- src/org/jgrapht/WeightedGraph.java | 71 ---- 14 files changed, 6 insertions(+), 985 deletions(-) rename src/org/{jgrapht => broadinstitute/compositetask}/DirectedGraph.java (98%) rename src/org/{jgrapht => broadinstitute/compositetask}/EdgeFactory.java (97%) rename src/org/{jgrapht => broadinstitute/compositetask}/Graph.java (99%) delete mode 100644 src/org/jgrapht/GraphHelper.java delete mode 100644 src/org/jgrapht/GraphMapping.java delete mode 100644 src/org/jgrapht/GraphPath.java delete mode 100644 src/org/jgrapht/Graphs.java delete mode 100644 src/org/jgrapht/ListenableGraph.java delete mode 100644 src/org/jgrapht/UndirectedGraph.java delete mode 100644 src/org/jgrapht/VertexFactory.java delete mode 100644 src/org/jgrapht/WeightedGraph.java diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/org/broadinstitute/compositetask/CompositeTask.java index 2c1c464..edd4b1f 100644 --- a/src/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/org/broadinstitute/compositetask/CompositeTask.java @@ -9,7 +9,6 @@ import java.util.LinkedHashSet; import java.util.HashMap; import java.util.Iterator; -import org.jgrapht.DirectedGraph; public class CompositeTask implements CompositeTaskScope { diff --git a/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java b/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java index 79bf5d2..4282cf8 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java @@ -1,7 +1,5 @@ package org.broadinstitute.compositetask; -import org.jgrapht.EdgeFactory; - public class CompositeTaskEdgeFactory implements EdgeFactory { public CompositeTaskEdge createEdge(CompositeTaskVertex sourceVertex, CompositeTaskVertex targetVertex) { diff --git a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java index 29ab0f8..c074e12 100644 --- a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java +++ b/src/org/broadinstitute/compositetask/CompositeTaskGraph.java @@ -8,8 +8,6 @@ import java.util.Comparator; import java.util.Collections; import java.util.Iterator; -import org.jgrapht.DirectedGraph; -import org.jgrapht.EdgeFactory; public class CompositeTaskGraph implements DirectedGraph { diff --git a/src/org/jgrapht/DirectedGraph.java b/src/org/broadinstitute/compositetask/DirectedGraph.java similarity index 98% rename from src/org/jgrapht/DirectedGraph.java rename to src/org/broadinstitute/compositetask/DirectedGraph.java index aa4d5b5..6f0fc5d 100644 --- a/src/org/jgrapht/DirectedGraph.java +++ b/src/org/broadinstitute/compositetask/DirectedGraph.java @@ -39,10 +39,10 @@ * 07-May-2006 : Changed from List to Set (JVS); * */ -package org.jgrapht; -import java.util.*; +package org.broadinstitute.compositetask; +import java.util.*; /** * A graph whose all edges are directed. This is the root interface of all diff --git a/src/org/jgrapht/EdgeFactory.java b/src/org/broadinstitute/compositetask/EdgeFactory.java similarity index 97% rename from src/org/jgrapht/EdgeFactory.java rename to src/org/broadinstitute/compositetask/EdgeFactory.java index c9b82af..6a0b4cc 100644 --- a/src/org/jgrapht/EdgeFactory.java +++ b/src/org/broadinstitute/compositetask/EdgeFactory.java @@ -38,7 +38,8 @@ * 11-Mar-2004 : Made generic (CH); * */ -package org.jgrapht; + +package org.broadinstitute.compositetask; /** * An edge factory used by graphs for creating new edges. diff --git a/src/org/jgrapht/Graph.java b/src/org/broadinstitute/compositetask/Graph.java similarity index 99% rename from src/org/jgrapht/Graph.java rename to src/org/broadinstitute/compositetask/Graph.java index 18ab404..29e6810 100644 --- a/src/org/jgrapht/Graph.java +++ b/src/org/broadinstitute/compositetask/Graph.java @@ -42,10 +42,10 @@ * 28-May-2006 : Moved connectivity info from edge to graph (JVS); * */ -package org.jgrapht; -import java.util.*; +package org.broadinstitute.compositetask; +import java.util.*; /** * The root interface in the graph hierarchy. A mathematical graph-theory graph diff --git a/src/org/jgrapht/GraphHelper.java b/src/org/jgrapht/GraphHelper.java deleted file mode 100644 index e45510a..0000000 --- a/src/org/jgrapht/GraphHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * GraphHelper.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * Mikael Hansen - * - * $Id$ - * - * Changes - * ------- - * 10-Jul-2003 : Initial revision (BN); - * 06-Nov-2003 : Change edge sharing semantics (JVS); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht; - -/** - * A collection of utilities to assist the working with graphs. - * - * @author Barak Naveh - * @since Jul 31, 2003 - * @deprecated Use {@link Graphs} instead. - */ -@Deprecated public abstract class GraphHelper - extends Graphs -{ -} - -// End GraphHelper.java diff --git a/src/org/jgrapht/GraphMapping.java b/src/org/jgrapht/GraphMapping.java deleted file mode 100644 index 1f70b58..0000000 --- a/src/org/jgrapht/GraphMapping.java +++ /dev/null @@ -1,75 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ----------------- - * GraphMapping.java - * ----------------- - * (C) Copyright 2005-2008, by Assaf Lehr and Contributors. - * - * Original Author: Assaf Lehr - * Contributor(s): John V. Sichi - * - * Changes - * ------- - */ -package org.jgrapht; - -/** - * GraphMapping represents a bidirectional mapping between two graphs (called - * graph1 and graph2), which allows the caller to obtain the matching vertex or - * edge in either direction, from graph1 to graph2, or from graph2 to graph1. It - * does not have to always be a complete bidirectional mapping (it could return - * null for some lookups). - * - * @author Assaf Lehr - * @since Jul 30, 2005 - */ -public interface GraphMapping -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Gets the mapped value where the key is vertex - * - * @param vertex vertex in one of the graphs - * @param forward if true, uses mapping from graph1 to graph2; if false, use - * mapping from graph2 to graph1 - * - * @return corresponding vertex in other graph, or null if none - */ - public V getVertexCorrespondence(V vertex, boolean forward); - - /** - * Gets the mapped value where the key is edge - * - * @param edge edge in one of the graphs - * @param forward if true, uses mapping from graph1 to graph2; if false, use - * mapping from graph2 to graph1 - * - * @return corresponding edge in other graph, or null if none - */ - public E getEdgeCorrespondence(E edge, boolean forward); -} - -// End GraphMapping.java diff --git a/src/org/jgrapht/GraphPath.java b/src/org/jgrapht/GraphPath.java deleted file mode 100644 index c08e679..0000000 --- a/src/org/jgrapht/GraphPath.java +++ /dev/null @@ -1,105 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------- - * Graph.java - * ---------- - * (C) Copyright 2008-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): - - * - * $Id$ - * - * Changes - * ------- - * 1-Jan-2008 : Initial revision (JVS); - * - */ -package org.jgrapht; - -import java.util.*; - - -/** - * A GraphPath represents a - * path in a {@link Graph}. Note that a path is defined primarily in terms - * of edges (rather than vertices) so that multiple edges between the same pair - * of vertices can be discriminated. - * - * @author John Sichi - * @since Jan 1, 2008 - */ -public interface GraphPath -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the graph over which this path is defined. The path may also be - * valid with respect to other graphs. - * - * @return the containing graph - */ - public Graph getGraph(); - - /** - * Returns the start vertex in the path. - * - * @return the start vertex - */ - public V getStartVertex(); - - /** - * Returns the end vertex in the path. - * - * @return the end vertex - */ - public V getEndVertex(); - - /** - * Returns the edges making up the path. The first edge in this path is - * incident to the start vertex. The last edge is incident to the end - * vertex. The vertices along the path can be obtained by traversing from - * the start vertex, finding its opposite across the first edge, and then - * doing the same successively across subsequent edges; {@link - * Graphs#getPathVertexList} provides a convenience method for this. - * - *

      Whether or not the returned edge list is modifiable depends on the - * path implementation. - * - * @return list of edges traversed by the path - */ - public List getEdgeList(); - - /** - * Returns the weight assigned to the path. Typically, this will be the sum - * of the weights of the edge list entries (as defined by the containing - * graph), but some path implementations may use other definitions. - * - * @return the weight of the path - */ - public double getWeight(); -} - -// End GraphPath.java diff --git a/src/org/jgrapht/Graphs.java b/src/org/jgrapht/Graphs.java deleted file mode 100644 index 0b2754b..0000000 --- a/src/org/jgrapht/Graphs.java +++ /dev/null @@ -1,442 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ---------------- - * Graphs.java - * ---------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * Mikael Hansen - * - * $Id$ - * - * Changes - * ------- - * 10-Jul-2003 : Initial revision (BN); - * 06-Nov-2003 : Change edge sharing semantics (JVS); - * 11-Mar-2004 : Made generic (CH); - * 07-May-2006 : Changed from List to Set (JVS); - * 28-May-2006 : Moved connectivity info from edge to graph (JVS); - * - */ -package org.jgrapht; - -import java.util.*; - -import org.jgrapht.graph.*; - - -/** - * A collection of utilities to assist with graph manipulation. - * - * @author Barak Naveh - * @since Jul 31, 2003 - */ -public abstract class Graphs -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Creates a new edge and adds it to the specified graph similarly to the - * {@link Graph#addEdge(Object, Object)} method. - * - * @param g the graph for which the edge to be added. - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @param weight weight of the edge. - * - * @return The newly created edge if added to the graph, otherwise - * null. - * - * @see Graph#addEdge(Object, Object) - */ - public static E addEdge( - Graph g, - V sourceVertex, - V targetVertex, - double weight) - { - EdgeFactory ef = g.getEdgeFactory(); - E e = ef.createEdge(sourceVertex, targetVertex); - - // we first create the edge and set the weight to make sure that - // listeners will see the correct weight upon addEdge. - - assert (g instanceof WeightedGraph) : g.getClass(); - ((WeightedGraph) g).setEdgeWeight(e, weight); - - return g.addEdge(sourceVertex, targetVertex, e) ? e : null; - } - - /** - * Adds the specified source and target vertices to the graph, if not - * already included, and creates a new edge and adds it to the specified - * graph similarly to the {@link Graph#addEdge(Object, Object)} method. - * - * @param g the graph for which the specified edge to be added. - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * - * @return The newly created edge if added to the graph, otherwise - * null. - */ - public static E addEdgeWithVertices( - Graph g, - V sourceVertex, - V targetVertex) - { - g.addVertex(sourceVertex); - g.addVertex(targetVertex); - - return g.addEdge(sourceVertex, targetVertex); - } - - /** - * Adds the specified edge to the graph, including its vertices if not - * already included. - * - * @param targetGraph the graph for which the specified edge to be added. - * @param sourceGraph the graph in which the specified edge is already - * present - * @param edge edge to add - * - * @return true if the target graph did not already contain the - * specified edge. - */ - public static boolean addEdgeWithVertices( - Graph targetGraph, - Graph sourceGraph, - E edge) - { - V sourceVertex = sourceGraph.getEdgeSource(edge); - V targetVertex = sourceGraph.getEdgeTarget(edge); - - targetGraph.addVertex(sourceVertex); - targetGraph.addVertex(targetVertex); - - return targetGraph.addEdge(sourceVertex, targetVertex, edge); - } - - /** - * Adds the specified source and target vertices to the graph, if not - * already included, and creates a new weighted edge and adds it to the - * specified graph similarly to the {@link Graph#addEdge(Object, Object)} - * method. - * - * @param g the graph for which the specified edge to be added. - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @param weight weight of the edge. - * - * @return The newly created edge if added to the graph, otherwise - * null. - */ - public static E addEdgeWithVertices( - Graph g, - V sourceVertex, - V targetVertex, - double weight) - { - g.addVertex(sourceVertex); - g.addVertex(targetVertex); - - return addEdge(g, sourceVertex, targetVertex, weight); - } - - /** - * Adds all the vertices and all the edges of the specified source graph to - * the specified destination graph. First all vertices of the source graph - * are added to the destination graph. Then every edge of the source graph - * is added to the destination graph. This method returns true - * if the destination graph has been modified as a result of this operation, - * otherwise it returns false. - * - *

      The behavior of this operation is undefined if any of the specified - * graphs is modified while operation is in progress.

      - * - * @param destination the graph to which vertices and edges are added. - * @param source the graph used as source for vertices and edges to add. - * - * @return true if and only if the destination graph has been - * changed as a result of this operation. - */ - public static boolean addGraph( - Graph destination, - Graph source) - { - boolean modified = addAllVertices(destination, source.vertexSet()); - modified |= addAllEdges(destination, source, source.edgeSet()); - - return modified; - } - - /** - * Adds all the vertices and all the edges of the specified source digraph - * to the specified destination digraph, reversing all of the edges. If you - * want to do this as a linked view of the source graph (rather than by - * copying to a destination graph), use {@link EdgeReversedGraph} instead. - * - *

      The behavior of this operation is undefined if any of the specified - * graphs is modified while operation is in progress.

      - * - * @param destination the graph to which vertices and edges are added. - * @param source the graph used as source for vertices and edges to add. - * - * @see EdgeReversedGraph - */ - public static void addGraphReversed( - DirectedGraph destination, - DirectedGraph source) - { - addAllVertices(destination, source.vertexSet()); - - for (E edge : source.edgeSet()) { - destination.addEdge( - source.getEdgeTarget(edge), - source.getEdgeSource(edge)); - } - } - - /** - * Adds a subset of the edges of the specified source graph to the specified - * destination graph. The behavior of this operation is undefined if either - * of the graphs is modified while the operation is in progress. {@link - * #addEdgeWithVertices} is used for the transfer, so source vertexes will - * be added automatically to the target graph. - * - * @param destination the graph to which edges are to be added - * @param source the graph used as a source for edges to add - * @param edges the edges to be added - * - * @return true if this graph changed as a result of the call - */ - public static boolean addAllEdges( - Graph destination, - Graph source, - Collection edges) - { - boolean modified = false; - - for (E e : edges) { - V s = source.getEdgeSource(e); - V t = source.getEdgeTarget(e); - destination.addVertex(s); - destination.addVertex(t); - modified |= destination.addEdge(s, t, e); - } - - return modified; - } - - /** - * Adds all of the specified vertices to the destination graph. The behavior - * of this operation is undefined if the specified vertex collection is - * modified while the operation is in progress. This method will invoke the - * {@link Graph#addVertex(Object)} method. - * - * @param destination the graph to which edges are to be added - * @param vertices the vertices to be added to the graph. - * - * @return true if graph changed as a result of the call - * - * @throws NullPointerException if the specified vertices contains one or - * more null vertices, or if the specified vertex collection is - * null. - * - * @see Graph#addVertex(Object) - */ - public static boolean addAllVertices( - Graph destination, - Collection vertices) - { - boolean modified = false; - - for (V v : vertices) { - modified |= destination.addVertex(v); - } - - return modified; - } - - /** - * Returns a list of vertices that are the neighbors of a specified vertex. - * If the graph is a multigraph vertices may appear more than once in the - * returned list. - * - * @param g the graph to look for neighbors in. - * @param vertex the vertex to get the neighbors of. - * - * @return a list of the vertices that are the neighbors of the specified - * vertex. - */ - public static List neighborListOf(Graph g, - V vertex) - { - List neighbors = new ArrayList(); - - for (E e : g.edgesOf(vertex)) { - neighbors.add(getOppositeVertex(g, e, vertex)); - } - - return neighbors; - } - - /** - * Returns a list of vertices that are the direct predecessors of a - * specified vertex. If the graph is a multigraph, vertices may appear more - * than once in the returned list. - * - * @param g the graph to look for predecessors in. - * @param vertex the vertex to get the predecessors of. - * - * @return a list of the vertices that are the direct predecessors of the - * specified vertex. - */ - public static List predecessorListOf( - DirectedGraph g, - V vertex) - { - List predecessors = new ArrayList(); - Set edges = g.incomingEdgesOf(vertex); - - for (E e : edges) { - predecessors.add(getOppositeVertex(g, e, vertex)); - } - - return predecessors; - } - - /** - * Returns a list of vertices that are the direct successors of a specified - * vertex. If the graph is a multigraph vertices may appear more than once - * in the returned list. - * - * @param g the graph to look for successors in. - * @param vertex the vertex to get the successors of. - * - * @return a list of the vertices that are the direct successors of the - * specified vertex. - */ - public static List successorListOf( - DirectedGraph g, - V vertex) - { - List successors = new ArrayList(); - Set edges = g.outgoingEdgesOf(vertex); - - for (E e : edges) { - successors.add(getOppositeVertex(g, e, vertex)); - } - - return successors; - } - - /** - * Returns an undirected view of the specified graph. If the specified graph - * is directed, returns an undirected view of it. If the specified graph is - * already undirected, just returns it. - * - * @param g the graph for which an undirected view is to be returned. - * - * @return an undirected view of the specified graph, if it is directed, or - * or the specified graph itself if it is already undirected. - * - * @throws IllegalArgumentException if the graph is neither DirectedGraph - * nor UndirectedGraph. - * - * @see AsUndirectedGraph - */ - public static UndirectedGraph undirectedGraph(Graph g) - { - if (g instanceof DirectedGraph) { - return new AsUndirectedGraph((DirectedGraph) g); - } else if (g instanceof UndirectedGraph) { - return (UndirectedGraph) g; - } else { - throw new IllegalArgumentException( - "Graph must be either DirectedGraph or UndirectedGraph"); - } - } - - /** - * Tests whether an edge is incident to a vertex. - * - * @param g graph containing e and v - * @param e edge in g - * @param v vertex in g - * - * @return true iff e is incident on v - */ - public static boolean testIncidence(Graph g, E e, V v) - { - return (g.getEdgeSource(e).equals(v)) - || (g.getEdgeTarget(e).equals(v)); - } - - /** - * Gets the vertex opposite another vertex across an edge. - * - * @param g graph containing e and v - * @param e edge in g - * @param v vertex in g - * - * @return vertex opposite to v across e - */ - public static V getOppositeVertex(Graph g, E e, V v) - { - V source = g.getEdgeSource(e); - V target = g.getEdgeTarget(e); - if (v.equals(source)) { - return target; - } else if (v.equals(target)) { - return source; - } else { - throw new IllegalArgumentException("no such vertex"); - } - } - - /** - * Gets the list of vertices visited by a path. - * - * @param path path of interest - * - * @return corresponding vertex list - */ - public static List getPathVertexList(GraphPath path) - { - Graph g = path.getGraph(); - List list = new ArrayList(); - V v = path.getStartVertex(); - list.add(v); - for (E e : path.getEdgeList()) { - v = getOppositeVertex(g, e, v); - list.add(v); - } - return list; - } -} - -// End Graphs.java diff --git a/src/org/jgrapht/ListenableGraph.java b/src/org/jgrapht/ListenableGraph.java deleted file mode 100644 index 7cba50d..0000000 --- a/src/org/jgrapht/ListenableGraph.java +++ /dev/null @@ -1,90 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------- - * ListenableGraph.java - * -------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 10-Aug-2003 : Adaptation to new event model (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht; - -import org.jgrapht.event.*; - - -/** - * A graph that supports listeners on structural change events. - * - * @author Barak Naveh - * @see GraphListener - * @see VertexSetListener - * @since Jul 20, 2003 - */ -public interface ListenableGraph - extends Graph -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Adds the specified graph listener to this graph, if not already present. - * - * @param l the listener to be added. - */ - public void addGraphListener(GraphListener l); - - /** - * Adds the specified vertex set listener to this graph, if not already - * present. - * - * @param l the listener to be added. - */ - public void addVertexSetListener(VertexSetListener l); - - /** - * Removes the specified graph listener from this graph, if present. - * - * @param l the listener to be removed. - */ - public void removeGraphListener(GraphListener l); - - /** - * Removes the specified vertex set listener from this graph, if present. - * - * @param l the listener to be removed. - */ - public void removeVertexSetListener(VertexSetListener l); -} - -// End ListenableGraph.java diff --git a/src/org/jgrapht/UndirectedGraph.java b/src/org/jgrapht/UndirectedGraph.java deleted file mode 100644 index 6429f16..0000000 --- a/src/org/jgrapht/UndirectedGraph.java +++ /dev/null @@ -1,70 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* -------------------- - * UndirectedGraph.java - * -------------------- - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht; - -/** - * A graph whose all edges are undirected. This is the root interface of all - * undirected graphs. - * - *

      See - * http://mathworld.wolfram.com/Graph.html for more on undirected and on - * directed graphs.

      - * - * @author Barak Naveh - * @since Jul 14, 2003 - */ -public interface UndirectedGraph - extends Graph -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the degree of the specified vertex. A degree of a vertex in an - * undirected graph is the number of edges touching that vertex. - * - * @param vertex vertex whose degree is to be calculated. - * - * @return the degree of the specified vertex. - */ - public int degreeOf(V vertex); -} - -// End UndirectedGraph.java diff --git a/src/org/jgrapht/VertexFactory.java b/src/org/jgrapht/VertexFactory.java deleted file mode 100644 index 86e8551..0000000 --- a/src/org/jgrapht/VertexFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * VertexFactory.java - * ------------------ - * (C) Copyright 2003-2008, by John V. Sichi and Contributors. - * - * Original Author: John V. Sichi - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 16-Sep-2003 : Initial revision (JVS); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht; - -/** - * A vertex factory used by graph algorithms for creating new vertices. - * Normally, vertices are constructed by user code and added to a graph - * explicitly, but algorithms which generate new vertices require a factory. - * - * @author John V. Sichi - * @since Sep 16, 2003 - */ -public interface VertexFactory -{ - //~ Methods ---------------------------------------------------------------- - - /** - * Creates a new vertex. - * - * @return the new vertex - */ - public V createVertex(); -} - -// End VertexFactory.java diff --git a/src/org/jgrapht/WeightedGraph.java b/src/org/jgrapht/WeightedGraph.java deleted file mode 100644 index 0d29745..0000000 --- a/src/org/jgrapht/WeightedGraph.java +++ /dev/null @@ -1,71 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------ - * WeightedGraph.java - * ------------------ - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * Original Author: Barak Naveh - * Contributor(s): Christian Hammer - * - * $Id$ - * - * Changes - * ------- - * 24-Jul-2003 : Initial revision (BN); - * 13-Aug-2003 : Included weight methods in Edge interface (BN); - * 11-Mar-2004 : Made generic (CH); - * - */ -package org.jgrapht; - -/** - * An interface for a graph whose edges have non-uniform weights. - * - * @author Barak Naveh - * @since Jul 23, 2003 - */ -public interface WeightedGraph - extends Graph -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * The default weight for an edge. - */ - public static double DEFAULT_EDGE_WEIGHT = 1.0; - - //~ Methods ---------------------------------------------------------------- - - /** - * Assigns a weight to an edge. - * - * @param e edge on which to set weight - * @param weight new weight for edge - */ - public void setEdgeWeight(E e, double weight); -} - -// End WeightedGraph.java From e1a3e10eca42686538c530feab0cb0cd09fee80a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 10:04:51 -0500 Subject: [PATCH 090/140] Translating to use Maven instead of Ant --- pom.xml | 50 ++++++++++++++++++++++ .../compositetask/AnsiColorizer.java | 0 .../org/broadinstitute/compositetask/Ast.java | 0 .../org/broadinstitute/compositetask/AstList.java | 0 .../org/broadinstitute/compositetask/AstNode.java | 0 .../broadinstitute/compositetask/AstTransform.java | 0 .../compositetask/AstTransformNodeCreator.java | 0 .../compositetask/AstTransformSubstitution.java | 0 .../broadinstitute/compositetask/ColorTheme.java | 0 .../compositetask/CompositeTask.java | 0 .../compositetask/CompositeTaskColorizer.java | 0 .../compositetask/CompositeTaskEdge.java | 0 .../compositetask/CompositeTaskEdgeFactory.java | 0 .../compositetask/CompositeTaskForLoop.java | 0 .../compositetask/CompositeTaskGraph.java | 0 .../compositetask/CompositeTaskNode.java | 0 .../compositetask/CompositeTaskScope.java | 0 .../compositetask/CompositeTaskSourceCode.java | 0 .../CompositeTaskSourceCodeFormatter.java | 0 .../compositetask/CompositeTaskStep.java | 0 .../compositetask/CompositeTaskStepInput.java | 0 .../compositetask/CompositeTaskStepOutput.java | 0 .../compositetask/CompositeTaskSubTask.java | 0 .../compositetask/CompositeTaskToDotCompiler.java | 0 .../compositetask/CompositeTaskVariable.java | 0 .../compositetask/CompositeTaskVertex.java | 0 .../compositetask/DirectedGraph.java | 0 .../broadinstitute/compositetask/EdgeFactory.java | 0 .../compositetask/ExpressionParser.java | 0 .../org/broadinstitute/compositetask/Graph.java | 0 .../compositetask/HtmlColorizer.java | 0 .../org/broadinstitute/compositetask/Lexer.java | 0 .../broadinstitute/compositetask/NonTerminal.java | 0 .../compositetask/NullColorizer.java | 0 .../broadinstitute/compositetask/ParseTree.java | 0 .../compositetask/ParseTreeNode.java | 0 .../org/broadinstitute/compositetask/Parser.java | 0 .../broadinstitute/compositetask/SourceCode.java | 0 .../broadinstitute/compositetask/SyntaxError.java | 0 .../compositetask/SyntaxErrorFormatter.java | 0 .../org/broadinstitute/compositetask/Terminal.java | 0 .../compositetask/TerminalIdentifier.java | 0 .../broadinstitute/compositetask/TerminalMap.java | 0 .../broadinstitute/compositetask/TokenStream.java | 0 .../org/broadinstitute/compositetask/Utility.java | 0 .../org/broadinstitute/compositetask/WdlMain.java | 0 .../broadinstitute/compositetask/WdlParser.java | 0 .../compositetask/WdlSyntaxErrorFormatter.java | 0 48 files changed, 50 insertions(+) create mode 100644 pom.xml rename src/{ => main/java}/org/broadinstitute/compositetask/AnsiColorizer.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Ast.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/AstList.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/AstNode.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/AstTransform.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/AstTransformNodeCreator.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/AstTransformSubstitution.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/ColorTheme.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTask.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskColorizer.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskEdge.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskForLoop.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskGraph.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskNode.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskScope.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskSourceCode.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskStep.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskStepInput.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskStepOutput.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskSubTask.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskVariable.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/CompositeTaskVertex.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/DirectedGraph.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/EdgeFactory.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/ExpressionParser.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Graph.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/HtmlColorizer.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Lexer.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/NonTerminal.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/NullColorizer.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/ParseTree.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/ParseTreeNode.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Parser.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/SourceCode.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/SyntaxError.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/SyntaxErrorFormatter.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Terminal.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/TerminalIdentifier.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/TerminalMap.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/TokenStream.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/Utility.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/WdlMain.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/WdlParser.java (100%) rename src/{ => main/java}/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java (100%) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..26cb3b2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,50 @@ + + + + UTF-8 + + + 4.0.0 + org.broadinstitute.compositetask + composite-task + jar + 0.0.1 + composite-task + http://github.com/broadinstitute/wdl + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + + org.broadinstitute.compositetask.WdlMain + + + + + + + org.codehaus.mojo + versions-maven-plugin + 1.3.1 + + + + + + + org.testng + testng + 6.8 + test + + + + diff --git a/src/org/broadinstitute/compositetask/AnsiColorizer.java b/src/main/java/org/broadinstitute/compositetask/AnsiColorizer.java similarity index 100% rename from src/org/broadinstitute/compositetask/AnsiColorizer.java rename to src/main/java/org/broadinstitute/compositetask/AnsiColorizer.java diff --git a/src/org/broadinstitute/compositetask/Ast.java b/src/main/java/org/broadinstitute/compositetask/Ast.java similarity index 100% rename from src/org/broadinstitute/compositetask/Ast.java rename to src/main/java/org/broadinstitute/compositetask/Ast.java diff --git a/src/org/broadinstitute/compositetask/AstList.java b/src/main/java/org/broadinstitute/compositetask/AstList.java similarity index 100% rename from src/org/broadinstitute/compositetask/AstList.java rename to src/main/java/org/broadinstitute/compositetask/AstList.java diff --git a/src/org/broadinstitute/compositetask/AstNode.java b/src/main/java/org/broadinstitute/compositetask/AstNode.java similarity index 100% rename from src/org/broadinstitute/compositetask/AstNode.java rename to src/main/java/org/broadinstitute/compositetask/AstNode.java diff --git a/src/org/broadinstitute/compositetask/AstTransform.java b/src/main/java/org/broadinstitute/compositetask/AstTransform.java similarity index 100% rename from src/org/broadinstitute/compositetask/AstTransform.java rename to src/main/java/org/broadinstitute/compositetask/AstTransform.java diff --git a/src/org/broadinstitute/compositetask/AstTransformNodeCreator.java b/src/main/java/org/broadinstitute/compositetask/AstTransformNodeCreator.java similarity index 100% rename from src/org/broadinstitute/compositetask/AstTransformNodeCreator.java rename to src/main/java/org/broadinstitute/compositetask/AstTransformNodeCreator.java diff --git a/src/org/broadinstitute/compositetask/AstTransformSubstitution.java b/src/main/java/org/broadinstitute/compositetask/AstTransformSubstitution.java similarity index 100% rename from src/org/broadinstitute/compositetask/AstTransformSubstitution.java rename to src/main/java/org/broadinstitute/compositetask/AstTransformSubstitution.java diff --git a/src/org/broadinstitute/compositetask/ColorTheme.java b/src/main/java/org/broadinstitute/compositetask/ColorTheme.java similarity index 100% rename from src/org/broadinstitute/compositetask/ColorTheme.java rename to src/main/java/org/broadinstitute/compositetask/ColorTheme.java diff --git a/src/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTask.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTask.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskColorizer.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskColorizer.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskColorizer.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskColorizer.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskEdge.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskEdge.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskEdgeFactory.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskForLoop.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskForLoop.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskGraph.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskGraph.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskNode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskNode.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskScope.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskScope.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskSourceCode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskSourceCode.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskStep.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskStep.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskStepInput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskStepInput.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskStepOutput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskStepOutput.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskSubTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSubTask.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskSubTask.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskSubTask.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskToDotCompiler.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskVariable.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskVariable.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java diff --git a/src/org/broadinstitute/compositetask/CompositeTaskVertex.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java similarity index 100% rename from src/org/broadinstitute/compositetask/CompositeTaskVertex.java rename to src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java diff --git a/src/org/broadinstitute/compositetask/DirectedGraph.java b/src/main/java/org/broadinstitute/compositetask/DirectedGraph.java similarity index 100% rename from src/org/broadinstitute/compositetask/DirectedGraph.java rename to src/main/java/org/broadinstitute/compositetask/DirectedGraph.java diff --git a/src/org/broadinstitute/compositetask/EdgeFactory.java b/src/main/java/org/broadinstitute/compositetask/EdgeFactory.java similarity index 100% rename from src/org/broadinstitute/compositetask/EdgeFactory.java rename to src/main/java/org/broadinstitute/compositetask/EdgeFactory.java diff --git a/src/org/broadinstitute/compositetask/ExpressionParser.java b/src/main/java/org/broadinstitute/compositetask/ExpressionParser.java similarity index 100% rename from src/org/broadinstitute/compositetask/ExpressionParser.java rename to src/main/java/org/broadinstitute/compositetask/ExpressionParser.java diff --git a/src/org/broadinstitute/compositetask/Graph.java b/src/main/java/org/broadinstitute/compositetask/Graph.java similarity index 100% rename from src/org/broadinstitute/compositetask/Graph.java rename to src/main/java/org/broadinstitute/compositetask/Graph.java diff --git a/src/org/broadinstitute/compositetask/HtmlColorizer.java b/src/main/java/org/broadinstitute/compositetask/HtmlColorizer.java similarity index 100% rename from src/org/broadinstitute/compositetask/HtmlColorizer.java rename to src/main/java/org/broadinstitute/compositetask/HtmlColorizer.java diff --git a/src/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java similarity index 100% rename from src/org/broadinstitute/compositetask/Lexer.java rename to src/main/java/org/broadinstitute/compositetask/Lexer.java diff --git a/src/org/broadinstitute/compositetask/NonTerminal.java b/src/main/java/org/broadinstitute/compositetask/NonTerminal.java similarity index 100% rename from src/org/broadinstitute/compositetask/NonTerminal.java rename to src/main/java/org/broadinstitute/compositetask/NonTerminal.java diff --git a/src/org/broadinstitute/compositetask/NullColorizer.java b/src/main/java/org/broadinstitute/compositetask/NullColorizer.java similarity index 100% rename from src/org/broadinstitute/compositetask/NullColorizer.java rename to src/main/java/org/broadinstitute/compositetask/NullColorizer.java diff --git a/src/org/broadinstitute/compositetask/ParseTree.java b/src/main/java/org/broadinstitute/compositetask/ParseTree.java similarity index 100% rename from src/org/broadinstitute/compositetask/ParseTree.java rename to src/main/java/org/broadinstitute/compositetask/ParseTree.java diff --git a/src/org/broadinstitute/compositetask/ParseTreeNode.java b/src/main/java/org/broadinstitute/compositetask/ParseTreeNode.java similarity index 100% rename from src/org/broadinstitute/compositetask/ParseTreeNode.java rename to src/main/java/org/broadinstitute/compositetask/ParseTreeNode.java diff --git a/src/org/broadinstitute/compositetask/Parser.java b/src/main/java/org/broadinstitute/compositetask/Parser.java similarity index 100% rename from src/org/broadinstitute/compositetask/Parser.java rename to src/main/java/org/broadinstitute/compositetask/Parser.java diff --git a/src/org/broadinstitute/compositetask/SourceCode.java b/src/main/java/org/broadinstitute/compositetask/SourceCode.java similarity index 100% rename from src/org/broadinstitute/compositetask/SourceCode.java rename to src/main/java/org/broadinstitute/compositetask/SourceCode.java diff --git a/src/org/broadinstitute/compositetask/SyntaxError.java b/src/main/java/org/broadinstitute/compositetask/SyntaxError.java similarity index 100% rename from src/org/broadinstitute/compositetask/SyntaxError.java rename to src/main/java/org/broadinstitute/compositetask/SyntaxError.java diff --git a/src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/SyntaxErrorFormatter.java similarity index 100% rename from src/org/broadinstitute/compositetask/SyntaxErrorFormatter.java rename to src/main/java/org/broadinstitute/compositetask/SyntaxErrorFormatter.java diff --git a/src/org/broadinstitute/compositetask/Terminal.java b/src/main/java/org/broadinstitute/compositetask/Terminal.java similarity index 100% rename from src/org/broadinstitute/compositetask/Terminal.java rename to src/main/java/org/broadinstitute/compositetask/Terminal.java diff --git a/src/org/broadinstitute/compositetask/TerminalIdentifier.java b/src/main/java/org/broadinstitute/compositetask/TerminalIdentifier.java similarity index 100% rename from src/org/broadinstitute/compositetask/TerminalIdentifier.java rename to src/main/java/org/broadinstitute/compositetask/TerminalIdentifier.java diff --git a/src/org/broadinstitute/compositetask/TerminalMap.java b/src/main/java/org/broadinstitute/compositetask/TerminalMap.java similarity index 100% rename from src/org/broadinstitute/compositetask/TerminalMap.java rename to src/main/java/org/broadinstitute/compositetask/TerminalMap.java diff --git a/src/org/broadinstitute/compositetask/TokenStream.java b/src/main/java/org/broadinstitute/compositetask/TokenStream.java similarity index 100% rename from src/org/broadinstitute/compositetask/TokenStream.java rename to src/main/java/org/broadinstitute/compositetask/TokenStream.java diff --git a/src/org/broadinstitute/compositetask/Utility.java b/src/main/java/org/broadinstitute/compositetask/Utility.java similarity index 100% rename from src/org/broadinstitute/compositetask/Utility.java rename to src/main/java/org/broadinstitute/compositetask/Utility.java diff --git a/src/org/broadinstitute/compositetask/WdlMain.java b/src/main/java/org/broadinstitute/compositetask/WdlMain.java similarity index 100% rename from src/org/broadinstitute/compositetask/WdlMain.java rename to src/main/java/org/broadinstitute/compositetask/WdlMain.java diff --git a/src/org/broadinstitute/compositetask/WdlParser.java b/src/main/java/org/broadinstitute/compositetask/WdlParser.java similarity index 100% rename from src/org/broadinstitute/compositetask/WdlParser.java rename to src/main/java/org/broadinstitute/compositetask/WdlParser.java diff --git a/src/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java similarity index 100% rename from src/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java rename to src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java From 9640c1b4cfac0c1e12974888f7fba60399d9fc00 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 10:08:39 -0500 Subject: [PATCH 091/140] Moving tests to Maven prescribed place --- .../test/java}/org/broadinstitute/compositetask/CompositeTaskTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {test => src/test/java}/org/broadinstitute/compositetask/CompositeTaskTest.java (100%) diff --git a/test/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java similarity index 100% rename from test/org/broadinstitute/compositetask/CompositeTaskTest.java rename to src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java From 9c5d7cf15d3d0d824f57e13bdd144c894e7e0f73 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 10:09:22 -0500 Subject: [PATCH 092/140] Don't need testng.jar anymore --- lib/testng-6.8.jar | Bin 1377303 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/testng-6.8.jar diff --git a/lib/testng-6.8.jar b/lib/testng-6.8.jar deleted file mode 100644 index 1e0e35f581acaa5c3acdc2feade0f90bfe2c20ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1377303 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 z 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
      6T3O&uRY}igP8^*3^c9YgYcaXJ0ioq`3wT&5 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
        +T(fA6O6nGQ~H3` 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

        ++^{ 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 (+*}WN& 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%0ACRtG+ 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

        k&s8n>UG(qD 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�!iL3P)-Qv2P0x~?Io}m$_EnTK%hz1|?qMeHv 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≧#mB6j{XSoh%yAa3&_v9Fe^ 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%0DIZr!R3alO90@c` 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 z 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 z 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≦$u#GR!tEP?7(4#uM#JTvOL1hvhDt?WVCZUXXeXq*5x1!JAtU= zs>+3*HpttQPRuZMn!Sv46*iO#`b5aQ@(?c_QzhnL`Rn+g7W!K9Ml1m-es$Y6l8K# zh4_b*kuak!L0U2>r7zd72dv^G-GQ~2lNp@tKPEN;0!=Sl;Q4}r^8%BVtNazTvS`gm zl$MNV*mIA3Ows+6adkt3OI+D1SA&6E`3_xFn9#^=vpy{z1s1@Q2fN!iR2xW1J*`z_ z{j>>9;dfnUfy~NYFl{_7mv6Q$JT@E{TE)bDTf|c;j%mYnwUjnk$bc^V*kdc9#d>L} zWEb2RnJeM!?E6-9T1vy22MHW2*D~bRAL<}D-l>|~J~iidd7$?a&QyR8a| zwqcIAX+|TN_iWQ_*UUdJ^lKTG#+9o@ZA_uMsKjQW>`^C63U!0aTo3mEm)*8 z4@%bDji#tk8}u@S@WW^h3+zmB>9;tAA{IrQbQPM3rvpx;+5JZ}854kZW&MudsahHu zIi$APOE6@zi#mfA_)`UNLpJHc^CqOTqI$oE|86X8%VtoEw4>qN7rhr zG6;mG5uIv+jC|_z4pWcTmC{R@0;hC+}hF~J4F_BxYZW_FOmBh8|J^P9+h zV?)GDAzQvnU{lz+5fjIYII>=p-l`5F@s}{3WDG}nQOFtM(Minl^d3v+#Pl)Hvi9aP zN?VSyh74Sb;gqNUd0MohV4ZF{-X^&GyE)WVNg7IkD;$TA#dO%BRfG~a6=EUO49DyF zNupTH+(C1VjeUC>6no0Ru%KOoB}MDniE=J)oTEuv8#(&B?EVW1tY&xvq~oHVk5gjt zr4_e`;y?kDwJB$AgTS?XI^67y4X2FHr-@qk*oc|QXuw126TsUS&I|-|xbde=&k4ws zi{E46=LZ&gl!6{Csg;@XG4G%wbxf!_L6-ZW8G2a6) zn>g6wkqI-PVHgySP(wDUh}`G5QOAndv-aF;nqTCQ zj9Y)yx{*nI!OHg72s9_%h+VjW4Y{Os@o3@90Jo!irS;P@%|#uznJjR%VYx+h3u*Vv ziurD67gX(5f2>iW7l3uLoD#E#0ACLkbDe9w0PO~eqZ=uhJJzj;acvr$tsq-6b5+1R zpH@ol5y`tXld6SMC|vP0!gDl_i1Nkrg*ls>mHCsUftsKjRdR!XsL@LW|8+t#>vL>; z7(T2Zo>CJ5!5Sr;lSTjrY^ZI1=z(HZw3riC&BBWanRd^K(1D}|z z%LK<2ZR6mlRl~V#S58ZL4Qoz_xgC^;;txUHQ+bJKbSSCtQ*n-&J&*06KD_gkp{a18 zUMRLutiUbN?=dZRu^HXCb_I66mPy%xo`lvdju0`MqVpzGT9{8~9_9EosB5Th6i9

        #bF`q^3Ld%|7>HSvIR-4(dH&Dwnx%-!OfkJ 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ⅆazWq}O_aU+{8dpl3N+T7rJ&WuPiVg~{g#9Bu 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 From 5d1cdc358d3be8602afdbbfac3b717e029da64a6 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 13:49:04 -0500 Subject: [PATCH 093/140] Removing most of the build targets in build.xml, leaving only the parser generation target --- build.xml | 76 ++------------------------------------------------------------- 1 file changed, 2 insertions(+), 74 deletions(-) diff --git a/build.xml b/build.xml index 40dd2dc..540348b 100644 --- a/build.xml +++ b/build.xml @@ -1,15 +1,5 @@ - - - - - - - - - - - - + + @@ -24,66 +14,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 77f06c941b3560da7f5dec519493c34c3698123d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 13:49:44 -0500 Subject: [PATCH 094/140] Updating README --- README.md | 30 +++++++++++++++++++++++++++--- pom.xml | 1 - 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e8046aa..e271b88 100644 --- a/README.md +++ b/README.md @@ -6,21 +6,42 @@ The Workflow Description Language is a language for describing dependency trees Installation ============ +Generating the JAR +------------------ + To build the JAR file, run: ``` -$ ant dist +$ mvn package +``` + +Which will create a file target/Wdl-${version}.jar as an executable JAR. To invoke the CLI: + +``` +$ java -jar target/Wdl-0.0.1.jar examples/0.wdl ast +``` + +Generating the parser code +-------------------------- + +Use the Hermes parser generator (http://github.com/scottfrazer/hermes). From the root of this repository, run: + +``` +$ hermes generate grammars/wdl.zgr --directory=src/main/java/org/broadinstitute/compositetask --language=java --java-package=org.broadinstitute.compositetask ``` -Which will create a file dist/Wdl-${version}.jar as an executable JAR. To invoke from the command line: +Or, run the Ant target `generate-parser` which will run the command above: ``` -$ java -jar dist/Wdl-0.0.1.jar examples/0.wdl ast +$ ant generate-parser ``` Usage ===== +Java API +-------- + From Java code, the main interface is the CompositeTask, which can be used in this example to print out the immediate children nodes of this composite task: ```java @@ -30,6 +51,9 @@ for ( CompositeTaskNode entry : ct.getNodes() ) { } ``` +Command-line Interface +---------------------- + The data file we'll use is: ``` diff --git a/pom.xml b/pom.xml index 26cb3b2..bb84196 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,6 @@ - org.apache.maven.plugins maven-jar-plugin From 62f2a68c4443f28827a752e4c5a381b6cf88a445 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 13:52:02 -0500 Subject: [PATCH 095/140] Renaming to Wdl (workflow description language) --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bb84196..eecbe44 100644 --- a/pom.xml +++ b/pom.xml @@ -7,10 +7,10 @@ 4.0.0 org.broadinstitute.compositetask - composite-task + Wdl jar 0.0.1 - composite-task + Wdl http://github.com/broadinstitute/wdl From 64ed98d3117a1962b878fdd201d961db699853af Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:07:21 -0500 Subject: [PATCH 096/140] renaming wdl.zgr -> composite_task.zgr --- grammars/{wdl.zgr => composite_task.zgr} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename grammars/{wdl.zgr => composite_task.zgr} (92%) diff --git a/grammars/wdl.zgr b/grammars/composite_task.zgr similarity index 92% rename from grammars/wdl.zgr rename to grammars/composite_task.zgr index a58793d..a533a36 100644 --- a/grammars/wdl.zgr +++ b/grammars/composite_task.zgr @@ -1,9 +1,9 @@ { "ll1": { - "start": "wdl", + "start": "composite_task", "rules": [ - "wdl := list(wdl_entity)", - "wdl_entity := composite_task", + "composite_task := list(composite_task_entity)", + "composite_task_entity := composite_task", "composite_task := 'composite_task' + 'identifier' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> CompositeTask( name=$1, body=$3 )", "composite_task_entity := step | for_loop | composite_task", "for_loop := 'for' + 'lparen' + 'identifier' + 'in' + 'identifier' + 'rparen' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )", From e997c97bfd8f55734d77017e94f4d9ab63e2ee7b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:07:54 -0500 Subject: [PATCH 097/140] Renaming WdlMain -> Main --- .../org/broadinstitute/compositetask/{WdlMain.java => Main.java} | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) rename src/main/java/org/broadinstitute/compositetask/{WdlMain.java => Main.java} (93%) diff --git a/src/main/java/org/broadinstitute/compositetask/WdlMain.java b/src/main/java/org/broadinstitute/compositetask/Main.java similarity index 93% rename from src/main/java/org/broadinstitute/compositetask/WdlMain.java rename to src/main/java/org/broadinstitute/compositetask/Main.java index 3003741..85d505f 100644 --- a/src/main/java/org/broadinstitute/compositetask/WdlMain.java +++ b/src/main/java/org/broadinstitute/compositetask/Main.java @@ -6,7 +6,12 @@ import java.util.Map; import java.util.Set; -public class WdlMain { +import org.broadinstitute.compositetask.parser.Utility; +import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.compositetask.parser.ParseTree; +import org.broadinstitute.compositetask.parser.SyntaxError; + +public class Main { public static void usage() { System.err.println("Usage: <.wdl file> "); From 000a68348eaa81a3731c36e40a89721d9c363dcc Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:11:50 -0500 Subject: [PATCH 098/140] new package org.broadinstitute.compositetask.parser --- .../broadinstitute/compositetask/AstTransform.java | 3 - .../broadinstitute/compositetask/ColorTheme.java | 2 + .../compositetask/CompositeTask.java | 13 +- .../compositetask/CompositeTaskForLoop.java | 3 + .../compositetask/CompositeTaskNode.java | 2 + .../compositetask/CompositeTaskSourceCode.java | 2 + .../CompositeTaskSourceCodeFormatter.java | 2 + .../compositetask/CompositeTaskStep.java | 2 + .../compositetask/CompositeTaskStepInput.java | 2 + .../compositetask/CompositeTaskStepOutput.java | 2 + .../compositetask/CompositeTaskVariable.java | 2 + .../org/broadinstitute/compositetask/Lexer.java | 49 +- .../compositetask/WdlSyntaxErrorFormatter.java | 6 + .../compositetask/{ => parser}/Ast.java | 2 +- .../compositetask/{ => parser}/AstList.java | 2 +- .../compositetask/{ => parser}/AstNode.java | 2 +- .../compositetask/parser/AstTransform.java | 3 + .../{ => parser}/AstTransformNodeCreator.java | 2 +- .../{ => parser}/AstTransformSubstitution.java | 2 +- .../CompositeTaskParser.java} | 1383 +++++++++----------- .../{ => parser}/ExpressionParser.java | 2 +- .../compositetask/{ => parser}/NonTerminal.java | 2 +- .../compositetask/{ => parser}/ParseTree.java | 2 +- .../compositetask/{ => parser}/ParseTreeNode.java | 2 +- .../compositetask/{ => parser}/Parser.java | 2 +- .../compositetask/{ => parser}/SourceCode.java | 2 +- .../compositetask/{ => parser}/SyntaxError.java | 2 +- .../{ => parser}/SyntaxErrorFormatter.java | 2 +- .../compositetask/{ => parser}/Terminal.java | 4 +- .../{ => parser}/TerminalIdentifier.java | 2 +- .../compositetask/{ => parser}/TerminalMap.java | 2 +- .../compositetask/{ => parser}/TokenStream.java | 6 +- .../compositetask/{ => parser}/Utility.java | 2 +- .../compositetask/CompositeTaskTest.java | 8 +- 34 files changed, 737 insertions(+), 789 deletions(-) delete mode 100644 src/main/java/org/broadinstitute/compositetask/AstTransform.java rename src/main/java/org/broadinstitute/compositetask/{ => parser}/Ast.java (97%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/AstList.java (92%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/AstNode.java (73%) create mode 100644 src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java rename src/main/java/org/broadinstitute/compositetask/{ => parser}/AstTransformNodeCreator.java (94%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/AstTransformSubstitution.java (86%) rename src/main/java/org/broadinstitute/compositetask/{WdlParser.java => parser/CompositeTaskParser.java} (77%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/ExpressionParser.java (71%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/NonTerminal.java (86%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/ParseTree.java (99%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/ParseTreeNode.java (77%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/Parser.java (70%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/SourceCode.java (84%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/SyntaxError.java (69%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/SyntaxErrorFormatter.java (94%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/Terminal.java (90%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/TerminalIdentifier.java (63%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/TerminalMap.java (74%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/TokenStream.java (93%) rename src/main/java/org/broadinstitute/compositetask/{ => parser}/Utility.java (98%) diff --git a/src/main/java/org/broadinstitute/compositetask/AstTransform.java b/src/main/java/org/broadinstitute/compositetask/AstTransform.java deleted file mode 100644 index 0ae30b6..0000000 --- a/src/main/java/org/broadinstitute/compositetask/AstTransform.java +++ /dev/null @@ -1,3 +0,0 @@ - -package org.broadinstitute.compositetask; -public interface AstTransform {} diff --git a/src/main/java/org/broadinstitute/compositetask/ColorTheme.java b/src/main/java/org/broadinstitute/compositetask/ColorTheme.java index d7864b9..8d1da24 100644 --- a/src/main/java/org/broadinstitute/compositetask/ColorTheme.java +++ b/src/main/java/org/broadinstitute/compositetask/ColorTheme.java @@ -2,6 +2,8 @@ import java.awt.Color; +import org.broadinstitute.compositetask.parser.Terminal; + public interface ColorTheme { Color getColor(Terminal terminal); } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index edd4b1f..996d5d0 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -10,6 +10,17 @@ import java.util.HashMap; import java.util.Iterator; +import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.compositetask.parser.AstNode; +import org.broadinstitute.compositetask.parser.AstList; +import org.broadinstitute.compositetask.parser.ParseTree; +import org.broadinstitute.compositetask.parser.ParseTreeNode; +import org.broadinstitute.compositetask.parser.SourceCode; +import org.broadinstitute.compositetask.parser.Terminal; +import org.broadinstitute.compositetask.parser.SyntaxError; +import org.broadinstitute.compositetask.parser.CompositeTaskParser; +import org.broadinstitute.compositetask.parser.TokenStream; + public class CompositeTask implements CompositeTaskScope { private ParseTree parse_tree; @@ -335,7 +346,7 @@ public String toString() { /** Private methods **/ private ParseTreeNode getParseTree(SourceCode source_code) throws SyntaxError { - WdlParser parser = new WdlParser(this.error_formatter); + CompositeTaskParser parser = new CompositeTaskParser(this.error_formatter); Lexer lexer = new Lexer(); List terminals = lexer.getTokens(source_code); TokenStream tokens = new TokenStream(terminals); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java index 9efbcb1..435d928 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java @@ -2,6 +2,9 @@ import java.util.Set; +import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.compositetask.parser.AstList; + public class CompositeTaskForLoop implements CompositeTaskScope { private CompositeTaskVariable collection; private CompositeTaskVariable var; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java index baeb1fb..1fd941d 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java @@ -1,5 +1,7 @@ package org.broadinstitute.compositetask; +import org.broadinstitute.compositetask.parser.Ast; + public interface CompositeTaskNode { public Ast getAst(); public void setParent(CompositeTaskScope parent); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java index 029515c..608e6e5 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java @@ -12,6 +12,8 @@ import java.util.List; import java.io.FileInputStream; +import org.broadinstitute.compositetask.parser.SourceCode; + public class CompositeTaskSourceCode implements SourceCode{ private File source; private String resource; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java index f5afe2d..c604b93 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; +import org.broadinstitute.compositetask.parser.Utility; + public class CompositeTaskSourceCodeFormatter { private CompositeTaskColorizer colorizer; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java index 8804702..775f34c 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java @@ -2,6 +2,8 @@ import java.util.Set; +import org.broadinstitute.compositetask.parser.Ast; + public class CompositeTaskStep implements CompositeTaskNode, CompositeTaskVertex { private CompositeTaskSubTask task; private String name; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java index 5a3e0b0..6be78d7 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java @@ -2,6 +2,8 @@ import java.util.Set; +import org.broadinstitute.compositetask.parser.Ast; + public class CompositeTaskStepInput { private String parameter; private CompositeTaskVariable variable; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java index 43bafc6..827ae12 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java @@ -2,6 +2,8 @@ import java.util.Set; +import org.broadinstitute.compositetask.parser.Ast; + public class CompositeTaskStepOutput { private String type; private String path; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java index c40e442..3eaaba1 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java @@ -2,6 +2,8 @@ import java.util.Set; +import org.broadinstitute.compositetask.parser.Ast; + public class CompositeTaskVariable implements CompositeTaskVertex { private String name; private String member; diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index 344a643..c3ba810 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -12,6 +12,7 @@ import java.nio.charset.*; import java.nio.channels.*; +import org.broadinstitute.compositetask.parser.*; class LexerMatch { private Terminal terminal; @@ -22,9 +23,9 @@ class TokenLexer { private Pattern regex; - private WdlParser.TerminalId terminal; + private CompositeTaskParser.TerminalId terminal; - TokenLexer(Pattern regex, WdlParser.TerminalId terminal) { + TokenLexer(Pattern regex, CompositeTaskParser.TerminalId terminal) { this.regex = regex; this.terminal = terminal; } @@ -54,28 +55,28 @@ LexerMatch match(SourceCode source) { this.regex = new ArrayList(); this.regex.add( new TokenLexer(Pattern.compile("\\/\\*.*?\\*\\/", Pattern.DOTALL), null) ); this.regex.add( new TokenLexer(Pattern.compile("//.*"), null) ); - this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); - this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_OUTPUT) ); - this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_INPUT) ); - this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_STEP) ); - this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FILE) ); - this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_FOR) ); - this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_AS) ); - this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), WdlParser.TerminalId.TERMINAL_IN) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\."), WdlParser.TerminalId.TERMINAL_DOT) ); - this.regex.add( new TokenLexer(Pattern.compile("^,"), WdlParser.TerminalId.TERMINAL_COMMA) ); - this.regex.add( new TokenLexer(Pattern.compile("^:"), WdlParser.TerminalId.TERMINAL_COLON) ); - this.regex.add( new TokenLexer(Pattern.compile("^;"), WdlParser.TerminalId.TERMINAL_SEMI) ); - this.regex.add( new TokenLexer(Pattern.compile("^="), WdlParser.TerminalId.TERMINAL_ASSIGN) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\["), WdlParser.TerminalId.TERMINAL_LSQUARE) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\]"), WdlParser.TerminalId.TERMINAL_RSQUARE) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\{"), WdlParser.TerminalId.TERMINAL_LBRACE) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\}"), WdlParser.TerminalId.TERMINAL_RBRACE) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\("), WdlParser.TerminalId.TERMINAL_LPAREN) ); - this.regex.add( new TokenLexer(Pattern.compile("^\\)"), WdlParser.TerminalId.TERMINAL_RPAREN) ); - this.regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), WdlParser.TerminalId.TERMINAL_STRING) ); - this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), WdlParser.TerminalId.TERMINAL_IDENTIFIER) ); - this.regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), WdlParser.TerminalId.TERMINAL_NUMBER) ); + this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); + this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); + this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); + this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); + this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) ); + this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_IN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\."), CompositeTaskParser.TerminalId.TERMINAL_DOT) ); + this.regex.add( new TokenLexer(Pattern.compile("^,"), CompositeTaskParser.TerminalId.TERMINAL_COMMA) ); + this.regex.add( new TokenLexer(Pattern.compile("^:"), CompositeTaskParser.TerminalId.TERMINAL_COLON) ); + this.regex.add( new TokenLexer(Pattern.compile("^;"), CompositeTaskParser.TerminalId.TERMINAL_SEMI) ); + this.regex.add( new TokenLexer(Pattern.compile("^="), CompositeTaskParser.TerminalId.TERMINAL_ASSIGN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\["), CompositeTaskParser.TerminalId.TERMINAL_LSQUARE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\]"), CompositeTaskParser.TerminalId.TERMINAL_RSQUARE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\{"), CompositeTaskParser.TerminalId.TERMINAL_LBRACE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\}"), CompositeTaskParser.TerminalId.TERMINAL_RBRACE) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\("), CompositeTaskParser.TerminalId.TERMINAL_LPAREN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\\)"), CompositeTaskParser.TerminalId.TERMINAL_RPAREN) ); + this.regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), CompositeTaskParser.TerminalId.TERMINAL_STRING) ); + this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), CompositeTaskParser.TerminalId.TERMINAL_IDENTIFIER) ); + this.regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), CompositeTaskParser.TerminalId.TERMINAL_NUMBER) ); this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); } diff --git a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java index ef89e0f..e29b352 100644 --- a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java @@ -3,6 +3,12 @@ import java.util.ArrayList; import java.util.List; +import org.broadinstitute.compositetask.parser.SyntaxErrorFormatter; +import org.broadinstitute.compositetask.parser.SourceCode; +import org.broadinstitute.compositetask.parser.Terminal; +import org.broadinstitute.compositetask.parser.TerminalIdentifier; +import org.broadinstitute.compositetask.parser.Utility; + public class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { private SourceCode code; public void setSourceCode(SourceCode code) { diff --git a/src/main/java/org/broadinstitute/compositetask/Ast.java b/src/main/java/org/broadinstitute/compositetask/parser/Ast.java similarity index 97% rename from src/main/java/org/broadinstitute/compositetask/Ast.java rename to src/main/java/org/broadinstitute/compositetask/parser/Ast.java index c26df6c..b6438ee 100644 --- a/src/main/java/org/broadinstitute/compositetask/Ast.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/Ast.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.Map; import java.util.LinkedList; import java.util.Formatter; diff --git a/src/main/java/org/broadinstitute/compositetask/AstList.java b/src/main/java/org/broadinstitute/compositetask/parser/AstList.java similarity index 92% rename from src/main/java/org/broadinstitute/compositetask/AstList.java rename to src/main/java/org/broadinstitute/compositetask/parser/AstList.java index 7405e1e..443c975 100644 --- a/src/main/java/org/broadinstitute/compositetask/AstList.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/AstList.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.ArrayList; public class AstList extends ArrayList implements AstNode { public String toString() { diff --git a/src/main/java/org/broadinstitute/compositetask/AstNode.java b/src/main/java/org/broadinstitute/compositetask/parser/AstNode.java similarity index 73% rename from src/main/java/org/broadinstitute/compositetask/AstNode.java rename to src/main/java/org/broadinstitute/compositetask/parser/AstNode.java index 1e5c788..bf306b4 100644 --- a/src/main/java/org/broadinstitute/compositetask/AstNode.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/AstNode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface AstNode { public String toString(); public String toPrettyString(); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java b/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java new file mode 100644 index 0000000..b6b4241 --- /dev/null +++ b/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java @@ -0,0 +1,3 @@ + +package org.broadinstitute.compositetask.parser; +public interface AstTransform {} diff --git a/src/main/java/org/broadinstitute/compositetask/AstTransformNodeCreator.java b/src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java similarity index 94% rename from src/main/java/org/broadinstitute/compositetask/AstTransformNodeCreator.java rename to src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java index 39292a8..627a579 100644 --- a/src/main/java/org/broadinstitute/compositetask/AstTransformNodeCreator.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.LinkedList; import java.util.Map; import java.util.LinkedHashMap; diff --git a/src/main/java/org/broadinstitute/compositetask/AstTransformSubstitution.java b/src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java similarity index 86% rename from src/main/java/org/broadinstitute/compositetask/AstTransformSubstitution.java rename to src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java index d5d9c3e..7019bae 100644 --- a/src/main/java/org/broadinstitute/compositetask/AstTransformSubstitution.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public class AstTransformSubstitution implements AstTransform { private int index; AstTransformSubstitution(int index) { diff --git a/src/main/java/org/broadinstitute/compositetask/WdlParser.java b/src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java similarity index 77% rename from src/main/java/org/broadinstitute/compositetask/WdlParser.java rename to src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java index c351a1a..d8b306a 100644 --- a/src/main/java/org/broadinstitute/compositetask/WdlParser.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java @@ -1,10 +1,10 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.*; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Arrays; -public class WdlParser implements Parser { +public class CompositeTaskParser implements Parser { private TokenStream tokens; private HashMap expressionParsers; private SyntaxErrorFormatter syntaxErrorFormatter; @@ -14,59 +14,56 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1 }, - { -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 6, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 32, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 20, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1 }, - { -1, -1, 42, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, 42, -1 }, - { -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 38, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, 36, -1, -1, -1, 33, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, 18, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1 }, - { -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, 22, -1, -1, -1 }, - { -1, -1, -1, 31, -1, 11, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 6, 6, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, 6, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 20, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22 }, + { 25, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 }, + { -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 8, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1 }, + { -1, -1, -1, -1, -1, 1, 27, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, 27, -1, -1, -1 }, + { -1, -1, -1, -1, -1, 15, 15, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, 15, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1 }, + { -1, -1, 29, -1, -1, -1, 14, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10 }, + { -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_FILE(0, "file"), - TERMINAL_COLON(1, "colon"), - TERMINAL_COMPOSITE_TASK(2, "composite_task"), - TERMINAL_IDENTIFIER(3, "identifier"), - TERMINAL_LPAREN(4, "lparen"), - TERMINAL_STRING(5, "string"), + TERMINAL_SEMI(0, "semi"), + TERMINAL_DOT(1, "dot"), + TERMINAL_INPUT(2, "input"), + TERMINAL_COLON(3, "colon"), + TERMINAL_NUMBER(4, "number"), + TERMINAL_COMPOSITE_TASK(5, "composite_task"), TERMINAL_RBRACE(6, "rbrace"), - TERMINAL_LSQUARE(7, "lsquare"), - TERMINAL_SEMI(8, "semi"), - TERMINAL_RSQUARE(9, "rsquare"), - TERMINAL_NUMBER(10, "number"), - TERMINAL_LBRACE(11, "lbrace"), - TERMINAL_COMMA(12, "comma"), - TERMINAL_AS(13, "as"), - TERMINAL_INPUT(14, "input"), - TERMINAL_IN(15, "in"), - TERMINAL_DOT(16, "dot"), - TERMINAL_STEP(17, "step"), - TERMINAL_OUTPUT(18, "output"), - TERMINAL_ASSIGN(19, "assign"), - TERMINAL_FOR(20, "for"), - TERMINAL_RPAREN(21, "rparen"); + TERMINAL_IDENTIFIER(7, "identifier"), + TERMINAL_AS(8, "as"), + TERMINAL_LBRACE(9, "lbrace"), + TERMINAL_IN(10, "in"), + TERMINAL_LPAREN(11, "lparen"), + TERMINAL_OUTPUT(12, "output"), + TERMINAL_RPAREN(13, "rparen"), + TERMINAL_LSQUARE(14, "lsquare"), + TERMINAL_FOR(15, "for"), + TERMINAL_FILE(16, "file"), + TERMINAL_ASSIGN(17, "assign"), + TERMINAL_STEP(18, "step"), + TERMINAL_RSQUARE(19, "rsquare"), + TERMINAL_STRING(20, "string"), + TERMINAL_COMMA(21, "comma"); private final int id; private final String string; TerminalId(int id, String string) { @@ -76,10 +73,10 @@ public int id() {return id;} public String string() {return string;} } - private class WdlTerminalMap implements TerminalMap { + private class CompositeTaskTerminalMap implements TerminalMap { private Map id_to_str; private Map str_to_id; - WdlTerminalMap(TerminalId[] terminals) { + CompositeTaskTerminalMap(TerminalId[] terminals) { id_to_str = new HashMap(); str_to_id = new HashMap(); for( TerminalId terminal : terminals ) { @@ -94,7 +91,7 @@ public boolean isValid(String string) { return this.str_to_id.containsKey(string); } public boolean isValid(int id) { return this.id_to_str.containsKey(id); } } - WdlParser(SyntaxErrorFormatter syntaxErrorFormatter) { + public CompositeTaskParser(SyntaxErrorFormatter syntaxErrorFormatter) { this.syntaxErrorFormatter = syntaxErrorFormatter; this.expressionParsers = new HashMap(); this.first = new HashMap(); @@ -103,237 +100,222 @@ this.rules = new HashMap(); ArrayList list; String rule; - this.nonterminal_rules.put("step", new ArrayList()); - this.nonterminal_rules.put("composite_task", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); - this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("_gen9", new ArrayList()); - this.nonterminal_rules.put("step_output_list", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); this.nonterminal_rules.put("_gen7", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); - this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("_gen3", new ArrayList()); this.nonterminal_rules.put("step_name", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); this.nonterminal_rules.put("composite_task_entity", new ArrayList()); - this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("_gen1", new ArrayList()); - this.nonterminal_rules.put("variable", new ArrayList()); - this.nonterminal_rules.put("_gen8", new ArrayList()); - this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("step", new ArrayList()); this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("_gen10", new ArrayList()); - this.nonterminal_rules.put("task_attrs", new ArrayList()); this.nonterminal_rules.put("step_attr", new ArrayList()); - this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("wdl_entity", new ArrayList()); - this.nonterminal_rules.put("_gen3", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("_gen9", new ArrayList()); + this.nonterminal_rules.put("task_identifier", new ArrayList()); this.nonterminal_rules.put("task_attr_value", new ArrayList()); - this.nonterminal_rules.put("wdl", new ArrayList()); - this.nonterminal_rules.put("step_output", new ArrayList()); - this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("task_attr", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); this.nonterminal_rules.put("_gen4", new ArrayList()); - rule = "_gen4 := task_attrs"; - this.nonterminal_rules.get("_gen4").add(rule); + this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("_gen8", new ArrayList()); + this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); + rule = "_gen3 := task_attrs"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(0), rule); - rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; - this.nonterminal_rules.get("step").add(rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen0 'rbrace' -> CompositeTask( body=$3, name=$1 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(1), rule); - rule = "_gen7 := 'comma' step_input _gen7"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "_gen1 := step_name"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(2), rule); - rule = "composite_task_entity := step"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(3), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + this.nonterminal_rules.get("task_attr").add(rule); this.rules.put(new Integer(4), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(5), rule); - rule = "_gen5 := task_attr _gen5"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "composite_task_entity := composite_task"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(6), rule); - rule = "_gen5 := ε"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(7), rule); - rule = "_gen9 := 'comma' step_output _gen9"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(8), rule); - rule = "variable := 'identifier' _gen10 -> Variable( member=$1, name=$0 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "_gen9 := variable_member"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(9), rule); - rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "_gen8 := 'comma' step_output _gen8"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(10), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen0 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(11), rule); - rule = "_gen2 := step_name"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); this.rules.put(new Integer(12), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "composite_task_entity := composite_task"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(13), rule); rule = "_gen2 := ε"; this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(14), rule); - rule = "wdl := _gen0"; - this.nonterminal_rules.get("wdl").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(15), rule); - rule = "_gen8 := ε"; - this.nonterminal_rules.get("_gen8").add(rule); - this.rules.put(new Integer(16), rule); - rule = "wdl_entity := composite_task"; - this.nonterminal_rules.get("wdl_entity").add(rule); - this.rules.put(new Integer(17), rule); rule = "step_attr := step_output_list"; this.nonterminal_rules.get("step_attr").add(rule); + this.rules.put(new Integer(16), rule); + rule = "task_attrs := 'lsquare' _gen4 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); + this.rules.put(new Integer(17), rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(18), rule); - rule = "composite_task_entity := composite_task"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "task_identifier := 'identifier' _gen3 -> Task( attributes=$1, name=$0 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(19), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen5 := ε"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(20), rule); - rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; - this.nonterminal_rules.get("step_input_list").add(rule); + rule = "_gen6 := ε"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(21), rule); - rule = "_gen3 := step_attr _gen3"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "_gen6 := 'comma' step_input _gen6"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(22), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "step_output_list := 'output' 'colon' _gen7 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(23), rule); rule = "variable_member := 'dot' 'identifier' -> $1"; this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(24), rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); + this.rules.put(new Integer(25), rule); rule = "_gen3 := ε"; this.nonterminal_rules.get("_gen3").add(rule); - this.rules.put(new Integer(25), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; - this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(26), rule); - rule = "step_name := 'as' 'identifier' -> $1"; - this.nonterminal_rules.get("step_name").add(rule); + rule = "composite_task := _gen0"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(27), rule); - rule = "_gen7 := ε"; - this.nonterminal_rules.get("_gen7").add(rule); - this.rules.put(new Integer(28), rule); rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; this.nonterminal_rules.get("step_input").add(rule); + this.rules.put(new Integer(28), rule); + rule = "_gen2 := step_attr _gen2"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(29), rule); - rule = "_gen6 := ε"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "_gen5 := step_input _gen6"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(30), rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; + this.nonterminal_rules.get("step_output").add(rule); + this.rules.put(new Integer(31), rule); rule = "task_attr_value := 'identifier'"; this.nonterminal_rules.get("task_attr_value").add(rule); - this.rules.put(new Integer(31), rule); - rule = "_gen6 := step_input _gen7"; - this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(32), rule); - rule = "_gen10 := variable_member"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "composite_task_entity := step"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(33), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(34), rule); - rule = "_gen4 := ε"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "step := 'step' task_identifier _gen1 'lbrace' _gen2 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; + this.nonterminal_rules.get("step").add(rule); this.rules.put(new Integer(35), rule); - rule = "_gen10 := ε"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "_gen4 := task_attr _gen4"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(36), rule); - rule = "task_attr_value := 'number'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "variable := 'identifier' _gen9 -> Variable( member=$1, name=$0 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(37), rule); - rule = "_gen8 := step_output _gen9"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "_gen7 := step_output _gen8"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(38), rule); - rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); - this.rules.put(new Integer(39), rule); - rule = "_gen0 := wdl_entity _gen0"; + rule = "_gen0 := composite_task_entity _gen0"; this.nonterminal_rules.get("_gen0").add(rule); + this.rules.put(new Integer(39), rule); + rule = "_gen7 := ε"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(40), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; - this.nonterminal_rules.get("task_attr").add(rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(41), rule); - rule = "_gen1 := composite_task_entity _gen1"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "step_input_list := 'input' 'colon' _gen5 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(42), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); - this.rules.put(new Integer(43), rule); - rule = "task_identifier := 'identifier' _gen4 -> Task( attributes=$1, name=$0 )"; - this.nonterminal_rules.get("task_identifier").add(rule); - this.rules.put(new Integer(44), rule); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); - this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); - this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); - this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_COMMA }); this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen0", new TerminalId[] { }); - this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_AS }); this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("wdl", new TerminalId[] { }); - this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); } public TerminalMap getTerminalMap() { - return new WdlTerminalMap(TerminalId.values()); + return new CompositeTaskTerminalMap(TerminalId.values()); } public ParseTree parse(TokenStream tokens) throws SyntaxError { this.tokens = tokens; this.tokens.setSyntaxErrorFormatter(this.syntaxErrorFormatter); this.tokens.setTerminalMap(this.getTerminalMap()); - ParseTree tree = this.parse_wdl(); + ParseTree tree = this.parse_composite_task(); if (this.tokens.current() != null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.excess_tokens(stack[1].getMethodName(), this.tokens.current())); @@ -344,102 +326,21 @@ private boolean isTerminal(TerminalId terminal) { return (0 <= terminal.id() && terminal.id() <= 21); } private boolean isNonTerminal(TerminalId terminal) { - return (22 <= terminal.id() && terminal.id() <= 50); + return (22 <= terminal.id() && terminal.id() <= 47); } private boolean isTerminal(int terminal) { return (0 <= terminal && terminal <= 21); } private boolean isNonTerminal(int terminal) { - return (22 <= terminal && terminal <= 50); + return (22 <= terminal && terminal <= 47); } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "step")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step", - Arrays.asList(this.first.get("step")), - this.nonterminal_rules.get("step") - )); - } - if (rule == 1) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 4); - parameters.put("task", 1); - parameters.put("name", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(1)); - tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen2(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(1)); - tree.add(next); - subtree = this.parse__gen3(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(1)); - tree.add(next); - return tree; - } - List terminals = Arrays.asList(this.first.get("step")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step", - current, - Arrays.asList(this.first.get("step")), - this.rules.get(1) - )); - } - private ParseTree parse_composite_task() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "composite_task")); + ParseTree tree = new ParseTree( new NonTerminal(22, "_gen1")); tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task", - Arrays.asList(this.first.get("composite_task")), - this.nonterminal_rules.get("composite_task") - )); - } - if (rule == 4) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(4)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(4)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(4)); - tree.add(next); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(4)); - tree.add(next); - return tree; - } - List terminals = Arrays.asList(this.first.get("composite_task")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task", - current, - Arrays.asList(this.first.get("composite_task")), - this.rules.get(4) - )); - } - private ParseTree parse__gen5() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen5")); - tree.setList("nlist"); if ( current != null ) { if (current.getId() == 9) { return tree; @@ -448,83 +349,46 @@ private ParseTree parse__gen5() throws SyntaxError { if (current == null) { return tree; } - if (rule == 6) { + if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); - tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "_gen0")); - tree.setList("nlist"); + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen7")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 0) { return tree; } } if (current == null) { return tree; } - if (rule == 40) { + if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen8(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "task_attr")); + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen3")); tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") - )); - } - if (rule == 41) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(41)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(41)); - tree.add(next); - subtree = this.parse_task_attr_value(); - tree.add( subtree); - return tree; - } - List terminals = Arrays.asList(this.first.get("task_attr")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", - current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(41) - )); - } - private ParseTree parse__gen9() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "_gen9")); - tree.setList("slist"); if ( current != null ) { if (current.getId() == 8) { return tree; @@ -533,188 +397,114 @@ private ParseTree parse__gen9() throws SyntaxError { if (current == null) { return tree; } - if (rule == 8) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(8)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen9(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "step_output_list")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "step_name")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") )); } - if (rule == 39) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(39)); + if (rule == 12) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(12)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(39)); - tree.add(next); - subtree = this.parse__gen8(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(39)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(12)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_list")); + List terminals = Arrays.asList(this.first.get("step_name")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", + "step_name", current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(39) + Arrays.asList(this.first.get("step_name")), + this.rules.get(12) )); } - private ParseTree parse__gen7() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "_gen7")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 8) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(2)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen6() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "_gen6")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 8) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 32) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse__gen2() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen2")); - tree.setList(null); - if ( current != null ) { - if (current.getId() == 11) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "step_name")); + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_name", - Arrays.asList(this.first.get("step_name")), - this.nonterminal_rules.get("step_name") + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") )); } - if (rule == 27) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(27)); + if (rule == 31) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(31)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(27)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(31)); tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(31)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(31)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(31)); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_name")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_name", + "step_output", current, - Arrays.asList(this.first.get("step_name")), - this.rules.get(27) + Arrays.asList(this.first.get("step_output")), + this.rules.get(31) )); } private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "composite_task_entity")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "composite_task_entity")); tree.setList(null); if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task_entity", - Arrays.asList(this.first.get("composite_task_entity")), - this.nonterminal_rules.get("composite_task_entity") - )); + return tree; } - if (rule == 3) { + if (rule == 6) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - else if (rule == 19) { + else if (rule == 13) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - else if (rule == 20) { + else if (rule == 33) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); + tree.add( subtree); + return tree; + } + else if (rule == 41) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_for_loop(); tree.add( subtree); @@ -725,135 +515,191 @@ else if (rule == 20) { "composite_task_entity", current, Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(20) + this.rules.get(41) )); } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "for_loop")); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "step")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "for_loop", - Arrays.asList(this.first.get("for_loop")), - this.nonterminal_rules.get("for_loop") + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") )); } - if (rule == 26) { + if (rule == 35) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(26)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(26)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(26)); + parameters.put("body", 4); + parameters.put("task", 1); + parameters.put("name", 2); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(35)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(26)); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(35)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(26)); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(35)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(26)); + return tree; + } + List terminals = Arrays.asList(this.first.get("step")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step", + current, + Arrays.asList(this.first.get("step")), + this.rules.get(35) + )); + } + private ParseTree parse_step_input() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "step_input")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") + )); + } + if (rule == 28) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(28)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(26)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(28)); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse_variable(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(26)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("for_loop")); + List terminals = Arrays.asList(this.first.get("step_input")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "for_loop", + "step_input", current, - Arrays.asList(this.first.get("for_loop")), - this.rules.get(26) + Arrays.asList(this.first.get("step_input")), + this.rules.get(28) )); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "_gen1")); - tree.setList("nlist"); + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "step_attr")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") + )); + } + if (rule == 16) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); + tree.add( subtree); + return tree; + } + else if (rule == 34) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input_list(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_attr", + current, + Arrays.asList(this.first.get("step_attr")), + this.rules.get(34) + )); + } + private ParseTree parse__gen5() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen5")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 0) { return tree; } } if (current == null) { return tree; } - if (rule == 42) { + if (rule == 30) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen1(); + subtree = this.parse__gen6(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "variable")); - tree.setList(null); + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "_gen6")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 0) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable", - Arrays.asList(this.first.get("variable")), - this.nonterminal_rules.get("variable") - )); + return tree; } - if (rule == 9) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(9)); + if (rule == 22) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen6", this.rules.get(22)); tree.add(next); - subtree = this.parse__gen10(); + tree.setListSeparator(next); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen6(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable", - current, - Arrays.asList(this.first.get("variable")), - this.rules.get(9) - )); + return tree; } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "_gen8")); - tree.setList("slist"); + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "_gen9")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 8) { + if (current.getId() == 21 || current.getId() == 0) { return tree; } } if (current == null) { return tree; } - if (rule == 38) { + if (rule == 9) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen9(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } @@ -863,8 +709,8 @@ private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "task_identifier")); + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "task_identifier")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -873,14 +719,14 @@ private ParseTree parse_task_identifier() throws SyntaxError { this.nonterminal_rules.get("task_identifier") )); } - if (rule == 44) { + if (rule == 19) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("attributes", 1); parameters.put("name", 0); tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(44)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(19)); tree.add(next); - subtree = this.parse__gen4(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } @@ -889,197 +735,246 @@ private ParseTree parse_task_identifier() throws SyntaxError { "task_identifier", current, Arrays.asList(this.first.get("task_identifier")), - this.rules.get(44) + this.rules.get(19) )); } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "step_input")); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 29) { + if (rule == 8) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(8)); + tree.add(next); + return tree; + } + else if (rule == 18) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(18)); + tree.add(next); + return tree; + } + else if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(32)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("task_attr_value")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr_value", + current, + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(32) + )); + } + private ParseTree parse_composite_task() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "composite_task")); + tree.setList(null); + if (current == null) { + return tree; + } + if (rule == 1) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(29)); + parameters.put("body", 3); + parameters.put("name", 1); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(1)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(29)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(1)); tree.add(next); - subtree = this.parse_variable(); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(1)); + tree.add(next); + subtree = this.parse__gen0(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(1)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); + else if (rule == 27) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", + "composite_task", current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(29) + Arrays.asList(this.first.get("composite_task")), + this.rules.get(27) )); } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen10")); - tree.setList(null); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "_gen0")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 12 || current.getId() == 8) { + if (current.getId() == -1 || current.getId() == 18 || current.getId() == 5 || current.getId() == 6 || current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 33) { + if (rule == 39) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_composite_task_entity(); + tree.add( subtree); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "task_attrs")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "task_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attrs", - Arrays.asList(this.first.get("task_attrs")), - this.nonterminal_rules.get("task_attrs") + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") )); } - if (rule == 10) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(10)); + if (rule == 4) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(4)); tree.add(next); - subtree = this.parse__gen5(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(10)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(4)); tree.add(next); + subtree = this.parse_task_attr_value(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attrs")); + List terminals = Arrays.asList(this.first.get("task_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attrs", + "task_attr", current, - Arrays.asList(this.first.get("task_attrs")), - this.rules.get(10) + Arrays.asList(this.first.get("task_attr")), + this.rules.get(4) )); } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "step_attr")); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "variable")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_attr", - Arrays.asList(this.first.get("step_attr")), - this.nonterminal_rules.get("step_attr") + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") )); } - if (rule == 5) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); - tree.add( subtree); - return tree; - } - else if (rule == 18) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + if (rule == 37) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("member", 1); + parameters.put("name", 0); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(37)); + tree.add(next); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_attr")); + List terminals = Arrays.asList(this.first.get("variable")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_attr", + "variable", current, - Arrays.asList(this.first.get("step_attr")), - this.rules.get(18) + Arrays.asList(this.first.get("variable")), + this.rules.get(37) )); } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "variable_member")); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "task_attrs")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") )); } - if (rule == 24) { + if (rule == 17) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(24)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(17)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(24)); + subtree = this.parse__gen4(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(17)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("variable_member")); + List terminals = Arrays.asList(this.first.get("task_attrs")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", + "task_attrs", current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(24) + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(17) )); } - private ParseTree parse_wdl_entity() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "wdl_entity")); - tree.setList(null); + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "_gen4")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 19) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "wdl_entity", - Arrays.asList(this.first.get("wdl_entity")), - this.nonterminal_rules.get("wdl_entity") - )); + return tree; } - if (rule == 17) { + if (rule == 36) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("wdl_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl_entity", - current, - Arrays.asList(this.first.get("wdl_entity")), - this.rules.get(17) - )); + return tree; } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "_gen3")); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "_gen2")); tree.setList("nlist"); if ( current != null ) { if (current.getId() == 6) { @@ -1089,178 +984,192 @@ private ParseTree parse__gen3() throws SyntaxError { if (current == null) { return tree; } - if (rule == 22) { + if (rule == 29) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse__gen2(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "task_attr_value")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr_value", - Arrays.asList(this.first.get("task_attr_value")), - this.nonterminal_rules.get("task_attr_value") - )); - } - if (rule == 11) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(11)); - tree.add(next); - return tree; + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "_gen8")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 0) { + return tree; + } } - else if (rule == 31) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(31)); - tree.add(next); + if (current == null) { return tree; } - else if (rule == 37) { + if (rule == 10) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(37)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen8", this.rules.get(10)); tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen8(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr_value")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr_value", - current, - Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(37) - )); + return tree; } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "wdl")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "step_input_list")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") + )); } - if (rule == 15) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); + if (rule == 42) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(42)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(42)); + tree.add(next); + subtree = this.parse__gen5(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(42)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("wdl")); + List terminals = Arrays.asList(this.first.get("step_input_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl", + "step_input_list", current, - Arrays.asList(this.first.get("wdl")), - this.rules.get(15) + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(42) )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "step_output")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "variable_member")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") )); } - if (rule == 23) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(23)); + if (rule == 24) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(24)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(23)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(24)); tree.add(next); - subtree = this.parse_variable(); - tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + List terminals = Arrays.asList(this.first.get("variable_member")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "variable_member", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(23) + Arrays.asList(this.first.get("variable_member")), + this.rules.get(24) )); } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "step_input_list")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") )); } - if (rule == 21) { + if (rule == 11) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(21)); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(11)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(21)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(11)); tree.add(next); - subtree = this.parse__gen6(); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(11)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(11)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(11)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(11)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(11)); + tree.add(next); + subtree = this.parse__gen0(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(21)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(11)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); + List terminals = Arrays.asList(this.first.get("for_loop")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", + "for_loop", current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(21) + Arrays.asList(this.first.get("for_loop")), + this.rules.get(11) )); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen4")); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "step_output_list")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 13) { - return tree; - } - } if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") + )); } - if (rule == 0) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + if (rule == 23) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(23)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(23)); + tree.add(next); + subtree = this.parse__gen7(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(23)); + tree.add(next); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("step_output_list")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_output_list", + current, + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(23) + )); } } diff --git a/src/main/java/org/broadinstitute/compositetask/ExpressionParser.java b/src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java similarity index 71% rename from src/main/java/org/broadinstitute/compositetask/ExpressionParser.java rename to src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java index b478cb7..1a89979 100644 --- a/src/main/java/org/broadinstitute/compositetask/ExpressionParser.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface ExpressionParser extends Parser { ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; } diff --git a/src/main/java/org/broadinstitute/compositetask/NonTerminal.java b/src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java similarity index 86% rename from src/main/java/org/broadinstitute/compositetask/NonTerminal.java rename to src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java index 70bd55d..46577b2 100644 --- a/src/main/java/org/broadinstitute/compositetask/NonTerminal.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public class NonTerminal { private int id; private String string; diff --git a/src/main/java/org/broadinstitute/compositetask/ParseTree.java b/src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java similarity index 99% rename from src/main/java/org/broadinstitute/compositetask/ParseTree.java rename to src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java index f9c0626..0b495b5 100644 --- a/src/main/java/org/broadinstitute/compositetask/ParseTree.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.ArrayList; import java.util.Map; import java.util.List; diff --git a/src/main/java/org/broadinstitute/compositetask/ParseTreeNode.java b/src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java similarity index 77% rename from src/main/java/org/broadinstitute/compositetask/ParseTreeNode.java rename to src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java index c3f045a..e61edd8 100644 --- a/src/main/java/org/broadinstitute/compositetask/ParseTreeNode.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface ParseTreeNode { public AstNode toAst(); public String toString(); diff --git a/src/main/java/org/broadinstitute/compositetask/Parser.java b/src/main/java/org/broadinstitute/compositetask/parser/Parser.java similarity index 70% rename from src/main/java/org/broadinstitute/compositetask/Parser.java rename to src/main/java/org/broadinstitute/compositetask/parser/Parser.java index 9467fef..8d88629 100644 --- a/src/main/java/org/broadinstitute/compositetask/Parser.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/Parser.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface Parser { ParseTree parse(TokenStream tokens) throws SyntaxError; TerminalMap getTerminalMap(); diff --git a/src/main/java/org/broadinstitute/compositetask/SourceCode.java b/src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java similarity index 84% rename from src/main/java/org/broadinstitute/compositetask/SourceCode.java rename to src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java index 4d4293d..9bfead7 100644 --- a/src/main/java/org/broadinstitute/compositetask/SourceCode.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.List; public interface SourceCode { public void advance(int amount); diff --git a/src/main/java/org/broadinstitute/compositetask/SyntaxError.java b/src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java similarity index 69% rename from src/main/java/org/broadinstitute/compositetask/SyntaxError.java rename to src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java index 8312fba..8094e0c 100644 --- a/src/main/java/org/broadinstitute/compositetask/SyntaxError.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public class SyntaxError extends Exception { public SyntaxError(String message) { super(message); diff --git a/src/main/java/org/broadinstitute/compositetask/SyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java similarity index 94% rename from src/main/java/org/broadinstitute/compositetask/SyntaxErrorFormatter.java rename to src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java index 4c7e425..8c3b665 100644 --- a/src/main/java/org/broadinstitute/compositetask/SyntaxErrorFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.List; public interface SyntaxErrorFormatter { /* Called when the parser runs out of tokens but isn't finished parsing. */ diff --git a/src/main/java/org/broadinstitute/compositetask/Terminal.java b/src/main/java/org/broadinstitute/compositetask/parser/Terminal.java similarity index 90% rename from src/main/java/org/broadinstitute/compositetask/Terminal.java rename to src/main/java/org/broadinstitute/compositetask/parser/Terminal.java index 894b330..f80cf21 100644 --- a/src/main/java/org/broadinstitute/compositetask/Terminal.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/Terminal.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.Formatter; import java.util.Locale; public class Terminal implements AstNode, ParseTreeNode @@ -10,7 +10,7 @@ private String resource; private int line; private int col; - Terminal(int id, String terminal_str, String source_string, String resource, int line, int col) { + public Terminal(int id, String terminal_str, String source_string, String resource, int line, int col) { this.id = id; this.terminal_str = terminal_str; this.source_string = source_string; diff --git a/src/main/java/org/broadinstitute/compositetask/TerminalIdentifier.java b/src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java similarity index 63% rename from src/main/java/org/broadinstitute/compositetask/TerminalIdentifier.java rename to src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java index 1a2f4e0..05e4814 100644 --- a/src/main/java/org/broadinstitute/compositetask/TerminalIdentifier.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface TerminalIdentifier { public int id(); public String string(); diff --git a/src/main/java/org/broadinstitute/compositetask/TerminalMap.java b/src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java similarity index 74% rename from src/main/java/org/broadinstitute/compositetask/TerminalMap.java rename to src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java index da03eda..54b3dac 100644 --- a/src/main/java/org/broadinstitute/compositetask/TerminalMap.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; public interface TerminalMap { int get(String string); String get(int id); diff --git a/src/main/java/org/broadinstitute/compositetask/TokenStream.java b/src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java similarity index 93% rename from src/main/java/org/broadinstitute/compositetask/TokenStream.java rename to src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java index 9fb0616..edcdc61 100644 --- a/src/main/java/org/broadinstitute/compositetask/TokenStream.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.ArrayList; import java.util.List; import java.util.Formatter; @@ -8,11 +8,11 @@ private int index; private TerminalMap terminals; private SyntaxErrorFormatter syntaxErrorFormatter; - TokenStream(List terminals) { + public TokenStream(List terminals) { super(terminals); reset(); } - TokenStream() { + public TokenStream() { reset(); } public void setTerminalMap(TerminalMap terminals) { diff --git a/src/main/java/org/broadinstitute/compositetask/Utility.java b/src/main/java/org/broadinstitute/compositetask/parser/Utility.java similarity index 98% rename from src/main/java/org/broadinstitute/compositetask/Utility.java rename to src/main/java/org/broadinstitute/compositetask/parser/Utility.java index f8a6e1d..ebe55a6 100644 --- a/src/main/java/org/broadinstitute/compositetask/Utility.java +++ b/src/main/java/org/broadinstitute/compositetask/parser/Utility.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask; +package org.broadinstitute.compositetask.parser; import java.util.Collection; import java.util.Iterator; import java.io.IOException; diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java index b06dad6..bcfe0ac 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -11,12 +11,14 @@ import java.util.ArrayList; import java.util.List; +import org.broadinstitute.compositetask.parser.SyntaxError; +import org.broadinstitute.compositetask.parser.SourceCode; +import org.broadinstitute.compositetask.parser.Terminal; +import org.broadinstitute.compositetask.parser.Utility; + import org.broadinstitute.compositetask.CompositeTask; -import org.broadinstitute.compositetask.SyntaxError; -import org.broadinstitute.compositetask.SourceCode; import org.broadinstitute.compositetask.CompositeTaskSourceCode; import org.broadinstitute.compositetask.Lexer; -import org.broadinstitute.compositetask.Terminal; public class CompositeTaskTest { From e289f71b4de91ff071d169fc40a978bd205db71b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:12:18 -0500 Subject: [PATCH 099/140] build file updates --- build.xml | 17 ++++++++++------- pom.xml | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/build.xml b/build.xml index 540348b..e333b8d 100644 --- a/build.xml +++ b/build.xml @@ -1,17 +1,20 @@ - + + + + + - - - + + - - + + - + diff --git a/pom.xml b/pom.xml index eecbe44..ed6941d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ - org.broadinstitute.compositetask.WdlMain + org.broadinstitute.compositetask.Main From 53c2bfeb91ded1accfc811c53059d2ae9837f2d4 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:37:19 -0500 Subject: [PATCH 100/140] Moving parser to org.broadinstitute.parser --- .../java/org/broadinstitute/compositetask/parser/AstTransform.java | 3 --- src/main/java/org/broadinstitute/{compositetask => }/parser/Ast.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/AstList.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/AstNode.java | 2 +- src/main/java/org/broadinstitute/parser/AstTransform.java | 3 +++ .../{compositetask => }/parser/AstTransformNodeCreator.java | 2 +- .../{compositetask => }/parser/AstTransformSubstitution.java | 2 +- .../broadinstitute/{compositetask => }/parser/CompositeTaskParser.java | 2 +- .../broadinstitute/{compositetask => }/parser/ExpressionParser.java | 2 +- .../org/broadinstitute/{compositetask => }/parser/NonTerminal.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/ParseTree.java | 2 +- .../org/broadinstitute/{compositetask => }/parser/ParseTreeNode.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/Parser.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/SourceCode.java | 2 +- .../org/broadinstitute/{compositetask => }/parser/SyntaxError.java | 2 +- .../{compositetask => }/parser/SyntaxErrorFormatter.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/Terminal.java | 2 +- .../broadinstitute/{compositetask => }/parser/TerminalIdentifier.java | 2 +- .../org/broadinstitute/{compositetask => }/parser/TerminalMap.java | 2 +- .../org/broadinstitute/{compositetask => }/parser/TokenStream.java | 2 +- .../java/org/broadinstitute/{compositetask => }/parser/Utility.java | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java rename src/main/java/org/broadinstitute/{compositetask => }/parser/Ast.java (97%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/AstList.java (92%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/AstNode.java (73%) create mode 100644 src/main/java/org/broadinstitute/parser/AstTransform.java rename src/main/java/org/broadinstitute/{compositetask => }/parser/AstTransformNodeCreator.java (94%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/AstTransformSubstitution.java (86%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/CompositeTaskParser.java (99%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/ExpressionParser.java (71%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/NonTerminal.java (86%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/ParseTree.java (99%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/ParseTreeNode.java (77%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/Parser.java (70%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/SourceCode.java (84%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/SyntaxError.java (69%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/SyntaxErrorFormatter.java (94%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/Terminal.java (96%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/TerminalIdentifier.java (63%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/TerminalMap.java (74%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/TokenStream.java (97%) rename src/main/java/org/broadinstitute/{compositetask => }/parser/Utility.java (98%) diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java b/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java deleted file mode 100644 index b6b4241..0000000 --- a/src/main/java/org/broadinstitute/compositetask/parser/AstTransform.java +++ /dev/null @@ -1,3 +0,0 @@ - -package org.broadinstitute.compositetask.parser; -public interface AstTransform {} diff --git a/src/main/java/org/broadinstitute/compositetask/parser/Ast.java b/src/main/java/org/broadinstitute/parser/Ast.java similarity index 97% rename from src/main/java/org/broadinstitute/compositetask/parser/Ast.java rename to src/main/java/org/broadinstitute/parser/Ast.java index b6438ee..98c53a8 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/Ast.java +++ b/src/main/java/org/broadinstitute/parser/Ast.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.Map; import java.util.LinkedList; import java.util.Formatter; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstList.java b/src/main/java/org/broadinstitute/parser/AstList.java similarity index 92% rename from src/main/java/org/broadinstitute/compositetask/parser/AstList.java rename to src/main/java/org/broadinstitute/parser/AstList.java index 443c975..fb6ca4d 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/AstList.java +++ b/src/main/java/org/broadinstitute/parser/AstList.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.ArrayList; public class AstList extends ArrayList implements AstNode { public String toString() { diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstNode.java b/src/main/java/org/broadinstitute/parser/AstNode.java similarity index 73% rename from src/main/java/org/broadinstitute/compositetask/parser/AstNode.java rename to src/main/java/org/broadinstitute/parser/AstNode.java index bf306b4..2023534 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/AstNode.java +++ b/src/main/java/org/broadinstitute/parser/AstNode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface AstNode { public String toString(); public String toPrettyString(); diff --git a/src/main/java/org/broadinstitute/parser/AstTransform.java b/src/main/java/org/broadinstitute/parser/AstTransform.java new file mode 100644 index 0000000..7ca7cce --- /dev/null +++ b/src/main/java/org/broadinstitute/parser/AstTransform.java @@ -0,0 +1,3 @@ + +package org.broadinstitute.parser; +public interface AstTransform {} diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java b/src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java similarity index 94% rename from src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java rename to src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java index 627a579..8ecf41d 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/AstTransformNodeCreator.java +++ b/src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.LinkedList; import java.util.Map; import java.util.LinkedHashMap; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java b/src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java similarity index 86% rename from src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java rename to src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java index 7019bae..f4dcbcb 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/AstTransformSubstitution.java +++ b/src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public class AstTransformSubstitution implements AstTransform { private int index; AstTransformSubstitution(int index) { diff --git a/src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java similarity index 99% rename from src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java rename to src/main/java/org/broadinstitute/parser/CompositeTaskParser.java index d8b306a..5f41f84 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/CompositeTaskParser.java +++ b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.*; import java.util.HashMap; import java.util.LinkedHashMap; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java b/src/main/java/org/broadinstitute/parser/ExpressionParser.java similarity index 71% rename from src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java rename to src/main/java/org/broadinstitute/parser/ExpressionParser.java index 1a89979..e27ca16 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/ExpressionParser.java +++ b/src/main/java/org/broadinstitute/parser/ExpressionParser.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface ExpressionParser extends Parser { ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError; } diff --git a/src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java b/src/main/java/org/broadinstitute/parser/NonTerminal.java similarity index 86% rename from src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java rename to src/main/java/org/broadinstitute/parser/NonTerminal.java index 46577b2..613898f 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/NonTerminal.java +++ b/src/main/java/org/broadinstitute/parser/NonTerminal.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public class NonTerminal { private int id; private String string; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java b/src/main/java/org/broadinstitute/parser/ParseTree.java similarity index 99% rename from src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java rename to src/main/java/org/broadinstitute/parser/ParseTree.java index 0b495b5..060dcb0 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/ParseTree.java +++ b/src/main/java/org/broadinstitute/parser/ParseTree.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.ArrayList; import java.util.Map; import java.util.List; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java b/src/main/java/org/broadinstitute/parser/ParseTreeNode.java similarity index 77% rename from src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java rename to src/main/java/org/broadinstitute/parser/ParseTreeNode.java index e61edd8..a3a530e 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/ParseTreeNode.java +++ b/src/main/java/org/broadinstitute/parser/ParseTreeNode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface ParseTreeNode { public AstNode toAst(); public String toString(); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/Parser.java b/src/main/java/org/broadinstitute/parser/Parser.java similarity index 70% rename from src/main/java/org/broadinstitute/compositetask/parser/Parser.java rename to src/main/java/org/broadinstitute/parser/Parser.java index 8d88629..e83aa2e 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/Parser.java +++ b/src/main/java/org/broadinstitute/parser/Parser.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface Parser { ParseTree parse(TokenStream tokens) throws SyntaxError; TerminalMap getTerminalMap(); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java b/src/main/java/org/broadinstitute/parser/SourceCode.java similarity index 84% rename from src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java rename to src/main/java/org/broadinstitute/parser/SourceCode.java index 9bfead7..0e101ff 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/SourceCode.java +++ b/src/main/java/org/broadinstitute/parser/SourceCode.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.List; public interface SourceCode { public void advance(int amount); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java b/src/main/java/org/broadinstitute/parser/SyntaxError.java similarity index 69% rename from src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java rename to src/main/java/org/broadinstitute/parser/SyntaxError.java index 8094e0c..caae11e 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/SyntaxError.java +++ b/src/main/java/org/broadinstitute/parser/SyntaxError.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public class SyntaxError extends Exception { public SyntaxError(String message) { super(message); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java similarity index 94% rename from src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java rename to src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java index 8c3b665..aa6dda7 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/SyntaxErrorFormatter.java +++ b/src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.List; public interface SyntaxErrorFormatter { /* Called when the parser runs out of tokens but isn't finished parsing. */ diff --git a/src/main/java/org/broadinstitute/compositetask/parser/Terminal.java b/src/main/java/org/broadinstitute/parser/Terminal.java similarity index 96% rename from src/main/java/org/broadinstitute/compositetask/parser/Terminal.java rename to src/main/java/org/broadinstitute/parser/Terminal.java index f80cf21..28034f8 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/Terminal.java +++ b/src/main/java/org/broadinstitute/parser/Terminal.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.Formatter; import java.util.Locale; public class Terminal implements AstNode, ParseTreeNode diff --git a/src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java b/src/main/java/org/broadinstitute/parser/TerminalIdentifier.java similarity index 63% rename from src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java rename to src/main/java/org/broadinstitute/parser/TerminalIdentifier.java index 05e4814..5690697 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/TerminalIdentifier.java +++ b/src/main/java/org/broadinstitute/parser/TerminalIdentifier.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface TerminalIdentifier { public int id(); public String string(); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java b/src/main/java/org/broadinstitute/parser/TerminalMap.java similarity index 74% rename from src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java rename to src/main/java/org/broadinstitute/parser/TerminalMap.java index 54b3dac..3cf3fa4 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/TerminalMap.java +++ b/src/main/java/org/broadinstitute/parser/TerminalMap.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; public interface TerminalMap { int get(String string); String get(int id); diff --git a/src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java b/src/main/java/org/broadinstitute/parser/TokenStream.java similarity index 97% rename from src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java rename to src/main/java/org/broadinstitute/parser/TokenStream.java index edcdc61..5a81fa9 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/TokenStream.java +++ b/src/main/java/org/broadinstitute/parser/TokenStream.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.ArrayList; import java.util.List; import java.util.Formatter; diff --git a/src/main/java/org/broadinstitute/compositetask/parser/Utility.java b/src/main/java/org/broadinstitute/parser/Utility.java similarity index 98% rename from src/main/java/org/broadinstitute/compositetask/parser/Utility.java rename to src/main/java/org/broadinstitute/parser/Utility.java index ebe55a6..0b87903 100644 --- a/src/main/java/org/broadinstitute/compositetask/parser/Utility.java +++ b/src/main/java/org/broadinstitute/parser/Utility.java @@ -1,5 +1,5 @@ -package org.broadinstitute.compositetask.parser; +package org.broadinstitute.parser; import java.util.Collection; import java.util.Iterator; import java.io.IOException; From ef098ca68e39cc7ab14db2235b93953278616b69 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:37:37 -0500 Subject: [PATCH 101/140] changing import statements --- .../org/broadinstitute/compositetask/ColorTheme.java | 2 +- .../broadinstitute/compositetask/CompositeTask.java | 20 ++++++++++---------- .../compositetask/CompositeTaskForLoop.java | 4 ++-- .../compositetask/CompositeTaskNode.java | 2 +- .../compositetask/CompositeTaskSourceCode.java | 2 +- .../CompositeTaskSourceCodeFormatter.java | 2 +- .../compositetask/CompositeTaskStep.java | 2 +- .../compositetask/CompositeTaskStepInput.java | 2 +- .../compositetask/CompositeTaskStepOutput.java | 2 +- .../compositetask/CompositeTaskVariable.java | 2 +- .../java/org/broadinstitute/compositetask/Lexer.java | 2 +- .../java/org/broadinstitute/compositetask/Main.java | 8 ++++---- .../compositetask/WdlSyntaxErrorFormatter.java | 10 +++++----- .../compositetask/CompositeTaskTest.java | 8 ++++---- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/ColorTheme.java b/src/main/java/org/broadinstitute/compositetask/ColorTheme.java index 8d1da24..bab51f8 100644 --- a/src/main/java/org/broadinstitute/compositetask/ColorTheme.java +++ b/src/main/java/org/broadinstitute/compositetask/ColorTheme.java @@ -2,7 +2,7 @@ import java.awt.Color; -import org.broadinstitute.compositetask.parser.Terminal; +import org.broadinstitute.parser.Terminal; public interface ColorTheme { Color getColor(Terminal terminal); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 996d5d0..0a0b24b 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -10,16 +10,16 @@ import java.util.HashMap; import java.util.Iterator; -import org.broadinstitute.compositetask.parser.Ast; -import org.broadinstitute.compositetask.parser.AstNode; -import org.broadinstitute.compositetask.parser.AstList; -import org.broadinstitute.compositetask.parser.ParseTree; -import org.broadinstitute.compositetask.parser.ParseTreeNode; -import org.broadinstitute.compositetask.parser.SourceCode; -import org.broadinstitute.compositetask.parser.Terminal; -import org.broadinstitute.compositetask.parser.SyntaxError; -import org.broadinstitute.compositetask.parser.CompositeTaskParser; -import org.broadinstitute.compositetask.parser.TokenStream; +import org.broadinstitute.parser.Ast; +import org.broadinstitute.parser.AstNode; +import org.broadinstitute.parser.AstList; +import org.broadinstitute.parser.ParseTree; +import org.broadinstitute.parser.ParseTreeNode; +import org.broadinstitute.parser.SourceCode; +import org.broadinstitute.parser.Terminal; +import org.broadinstitute.parser.SyntaxError; +import org.broadinstitute.parser.CompositeTaskParser; +import org.broadinstitute.parser.TokenStream; public class CompositeTask implements CompositeTaskScope { diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java index 435d928..41cea93 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java @@ -2,8 +2,8 @@ import java.util.Set; -import org.broadinstitute.compositetask.parser.Ast; -import org.broadinstitute.compositetask.parser.AstList; +import org.broadinstitute.parser.Ast; +import org.broadinstitute.parser.AstList; public class CompositeTaskForLoop implements CompositeTaskScope { private CompositeTaskVariable collection; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java index 1fd941d..36eddb5 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskNode.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.parser.Ast; public interface CompositeTaskNode { public Ast getAst(); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java index 608e6e5..60f8303 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java @@ -12,7 +12,7 @@ import java.util.List; import java.io.FileInputStream; -import org.broadinstitute.compositetask.parser.SourceCode; +import org.broadinstitute.parser.SourceCode; public class CompositeTaskSourceCode implements SourceCode{ private File source; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java index c604b93..46174b4 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import org.broadinstitute.compositetask.parser.Utility; +import org.broadinstitute.parser.Utility; public class CompositeTaskSourceCodeFormatter { private CompositeTaskColorizer colorizer; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java index 775f34c..3a0ee94 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java @@ -2,7 +2,7 @@ import java.util.Set; -import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.parser.Ast; public class CompositeTaskStep implements CompositeTaskNode, CompositeTaskVertex { private CompositeTaskSubTask task; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java index 6be78d7..ca3b450 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepInput.java @@ -2,7 +2,7 @@ import java.util.Set; -import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.parser.Ast; public class CompositeTaskStepInput { private String parameter; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java index 827ae12..78b2f72 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java @@ -2,7 +2,7 @@ import java.util.Set; -import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.parser.Ast; public class CompositeTaskStepOutput { private String type; diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java index 3eaaba1..38869ea 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java @@ -2,7 +2,7 @@ import java.util.Set; -import org.broadinstitute.compositetask.parser.Ast; +import org.broadinstitute.parser.Ast; public class CompositeTaskVariable implements CompositeTaskVertex { private String name; diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index c3ba810..e855bd2 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -12,7 +12,7 @@ import java.nio.charset.*; import java.nio.channels.*; -import org.broadinstitute.compositetask.parser.*; +import org.broadinstitute.parser.*; class LexerMatch { private Terminal terminal; diff --git a/src/main/java/org/broadinstitute/compositetask/Main.java b/src/main/java/org/broadinstitute/compositetask/Main.java index 85d505f..e4bdc99 100644 --- a/src/main/java/org/broadinstitute/compositetask/Main.java +++ b/src/main/java/org/broadinstitute/compositetask/Main.java @@ -6,10 +6,10 @@ import java.util.Map; import java.util.Set; -import org.broadinstitute.compositetask.parser.Utility; -import org.broadinstitute.compositetask.parser.Ast; -import org.broadinstitute.compositetask.parser.ParseTree; -import org.broadinstitute.compositetask.parser.SyntaxError; +import org.broadinstitute.parser.Utility; +import org.broadinstitute.parser.Ast; +import org.broadinstitute.parser.ParseTree; +import org.broadinstitute.parser.SyntaxError; public class Main { diff --git a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java index e29b352..fdb53f8 100644 --- a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java @@ -3,11 +3,11 @@ import java.util.ArrayList; import java.util.List; -import org.broadinstitute.compositetask.parser.SyntaxErrorFormatter; -import org.broadinstitute.compositetask.parser.SourceCode; -import org.broadinstitute.compositetask.parser.Terminal; -import org.broadinstitute.compositetask.parser.TerminalIdentifier; -import org.broadinstitute.compositetask.parser.Utility; +import org.broadinstitute.parser.SyntaxErrorFormatter; +import org.broadinstitute.parser.SourceCode; +import org.broadinstitute.parser.Terminal; +import org.broadinstitute.parser.TerminalIdentifier; +import org.broadinstitute.parser.Utility; public class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter { private SourceCode code; diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java index bcfe0ac..cfb0929 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -11,10 +11,10 @@ import java.util.ArrayList; import java.util.List; -import org.broadinstitute.compositetask.parser.SyntaxError; -import org.broadinstitute.compositetask.parser.SourceCode; -import org.broadinstitute.compositetask.parser.Terminal; -import org.broadinstitute.compositetask.parser.Utility; +import org.broadinstitute.parser.SyntaxError; +import org.broadinstitute.parser.SourceCode; +import org.broadinstitute.parser.Terminal; +import org.broadinstitute.parser.Utility; import org.broadinstitute.compositetask.CompositeTask; import org.broadinstitute.compositetask.CompositeTaskSourceCode; From caf58ae267f4ab0875676459c37042052cf2c66e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 27 Nov 2012 15:38:05 -0500 Subject: [PATCH 102/140] changing generate-parser target --- build.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index e333b8d..53fba5e 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,7 @@ - - + + From 3d82358dfe57ebd21a38efd84944b5d294bd62fd Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 4 Dec 2012 16:11:54 -0500 Subject: [PATCH 103/140] Fixing issue where FileInputStream wasn't being closed by CompositeTaskSourceCode --- .../org/broadinstitute/compositetask/CompositeTaskSourceCode.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java index 60f8303..b9b423c 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCode.java @@ -14,7 +14,7 @@ import org.broadinstitute.parser.SourceCode; -public class CompositeTaskSourceCode implements SourceCode{ +public class CompositeTaskSourceCode implements SourceCode { private File source; private String resource; private String contents; @@ -36,11 +36,14 @@ } CompositeTaskSourceCode(File source, String encoding, String resource) throws IOException, FileNotFoundException { - FileChannel channel = new FileInputStream(source).getChannel(); + FileInputStream in = new FileInputStream(source); + FileChannel channel = in.getChannel(); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); Charset cs = Charset.forName(encoding); CharsetDecoder cd = cs.newDecoder(); CharBuffer cb = cd.decode(buffer); + in.close(); + init(cb.toString(), resource); } From 0bf7cff07c4e3beba3452b2ca0142abbcf130c2d Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 4 Dec 2012 16:12:13 -0500 Subject: [PATCH 104/140] Adding Javadoc plugin to POM --- pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pom.xml b/pom.xml index ed6941d..e65600f 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,16 @@ versions-maven-plugin 1.3.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + private + true + + From 8a3c94ef828c0531e858f8d1e005a927e3ccfbae Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 5 Dec 2012 11:57:05 -0500 Subject: [PATCH 105/140] Adding tokenizing functionality to the CLI --- src/main/java/org/broadinstitute/compositetask/Main.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/compositetask/Main.java b/src/main/java/org/broadinstitute/compositetask/Main.java index e4bdc99..6296054 100644 --- a/src/main/java/org/broadinstitute/compositetask/Main.java +++ b/src/main/java/org/broadinstitute/compositetask/Main.java @@ -10,13 +10,15 @@ import org.broadinstitute.parser.Ast; import org.broadinstitute.parser.ParseTree; import org.broadinstitute.parser.SyntaxError; +import org.broadinstitute.parser.Terminal; public class Main { public static void usage() { - System.err.println("Usage: <.wdl file> "); + System.err.println("Usage: <.wdl file> "); System.err.println(); System.err.println("Actions:"); + System.err.println(" tokens: tokenize the source code"); System.err.println(" ast: parse source code and output an abstract syntax tree"); System.err.println(" parsetree: parse source code and output a parsetree"); System.err.println(" entities: output an abbreviated view of all entities and which scope they're nested in"); @@ -34,6 +36,16 @@ public static void main(String[] args) { } try { + + if ( args[1].equals("tokens") ) { + Lexer lexer = new Lexer(); + List terminals = lexer.getTokens(new CompositeTaskSourceCode(new File(args[0]))); + for ( Terminal terminal : terminals ) { + System.out.println(terminal); + } + System.exit(0); + } + CompositeTask ctask = new CompositeTask(new File(args[0])); if ( args[1].equals("ast") ) { From c7a0c8a1d73417ce93e0143c0d58b19762346b0b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 5 Dec 2012 12:10:20 -0500 Subject: [PATCH 106/140] Fixing bug with incorrectly generated parser --- grammars/composite_task.zgr | 6 +- .../broadinstitute/parser/CompositeTaskParser.java | 1319 +++++++++++--------- 2 files changed, 708 insertions(+), 617 deletions(-) diff --git a/grammars/composite_task.zgr b/grammars/composite_task.zgr index a533a36..a58793d 100644 --- a/grammars/composite_task.zgr +++ b/grammars/composite_task.zgr @@ -1,9 +1,9 @@ { "ll1": { - "start": "composite_task", + "start": "wdl", "rules": [ - "composite_task := list(composite_task_entity)", - "composite_task_entity := composite_task", + "wdl := list(wdl_entity)", + "wdl_entity := composite_task", "composite_task := 'composite_task' + 'identifier' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> CompositeTask( name=$1, body=$3 )", "composite_task_entity := step | for_loop | composite_task", "for_loop := 'for' + 'lparen' + 'identifier' + 'in' + 'identifier' + 'rparen' + 'lbrace' + list(composite_task_entity) + 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )", diff --git a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java index 5f41f84..a843193 100644 --- a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java +++ b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java @@ -14,56 +14,59 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 6, 6, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, 6, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 20, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22 }, - { 25, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 }, - { -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, 8, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1 }, - { -1, -1, -1, -1, -1, 1, 27, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, 27, -1, -1, -1 }, - { -1, -1, -1, -1, -1, 15, 15, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, 15, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1 }, - { -1, -1, 29, -1, -1, -1, 14, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10 }, - { -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 2, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, 34, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15 }, + { -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 21, 21, -1, -1, -1, -1, -1, -1, 14, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 36, 38, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 20, 32, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, 1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, 41, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1 }, + { 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, 39, -1, 31, -1, -1 }, + { -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 12, 8, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_SEMI(0, "semi"), - TERMINAL_DOT(1, "dot"), - TERMINAL_INPUT(2, "input"), - TERMINAL_COLON(3, "colon"), - TERMINAL_NUMBER(4, "number"), - TERMINAL_COMPOSITE_TASK(5, "composite_task"), - TERMINAL_RBRACE(6, "rbrace"), - TERMINAL_IDENTIFIER(7, "identifier"), - TERMINAL_AS(8, "as"), - TERMINAL_LBRACE(9, "lbrace"), - TERMINAL_IN(10, "in"), - TERMINAL_LPAREN(11, "lparen"), - TERMINAL_OUTPUT(12, "output"), - TERMINAL_RPAREN(13, "rparen"), - TERMINAL_LSQUARE(14, "lsquare"), - TERMINAL_FOR(15, "for"), - TERMINAL_FILE(16, "file"), - TERMINAL_ASSIGN(17, "assign"), - TERMINAL_STEP(18, "step"), - TERMINAL_RSQUARE(19, "rsquare"), - TERMINAL_STRING(20, "string"), - TERMINAL_COMMA(21, "comma"); + TERMINAL_LBRACE(0, "lbrace"), + TERMINAL_FOR(1, "for"), + TERMINAL_COMPOSITE_TASK(2, "composite_task"), + TERMINAL_LPAREN(3, "lparen"), + TERMINAL_IN(4, "in"), + TERMINAL_ASSIGN(5, "assign"), + TERMINAL_IDENTIFIER(6, "identifier"), + TERMINAL_STRING(7, "string"), + TERMINAL_OUTPUT(8, "output"), + TERMINAL_RBRACE(9, "rbrace"), + TERMINAL_STEP(10, "step"), + TERMINAL_INPUT(11, "input"), + TERMINAL_COLON(12, "colon"), + TERMINAL_AS(13, "as"), + TERMINAL_NUMBER(14, "number"), + TERMINAL_SEMI(15, "semi"), + TERMINAL_LSQUARE(16, "lsquare"), + TERMINAL_DOT(17, "dot"), + TERMINAL_FILE(18, "file"), + TERMINAL_COMMA(19, "comma"), + TERMINAL_RPAREN(20, "rparen"), + TERMINAL_RSQUARE(21, "rsquare"); private final int id; private final String string; TerminalId(int id, String string) { @@ -100,213 +103,228 @@ public CompositeTaskParser(SyntaxErrorFormatter syntaxErrorFormatter) { this.rules = new HashMap(); ArrayList list; String rule; - this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("task_attr", new ArrayList()); this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); this.nonterminal_rules.put("_gen3", new ArrayList()); - this.nonterminal_rules.put("step_name", new ArrayList()); - this.nonterminal_rules.put("step_output", new ArrayList()); this.nonterminal_rules.put("composite_task_entity", new ArrayList()); - this.nonterminal_rules.put("step", new ArrayList()); - this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("step_attr", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); this.nonterminal_rules.put("_gen9", new ArrayList()); this.nonterminal_rules.put("task_identifier", new ArrayList()); - this.nonterminal_rules.put("task_attr_value", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); this.nonterminal_rules.put("composite_task", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); - this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("variable", new ArrayList()); - this.nonterminal_rules.put("task_attrs", new ArrayList()); - this.nonterminal_rules.put("_gen4", new ArrayList()); - this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("step_input", new ArrayList()); this.nonterminal_rules.put("_gen8", new ArrayList()); + this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("step_name", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); + this.nonterminal_rules.put("_gen2", new ArrayList()); this.nonterminal_rules.put("step_input_list", new ArrayList()); - this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("step_output_list", new ArrayList()); - rule = "_gen3 := task_attrs"; - this.nonterminal_rules.get("_gen3").add(rule); + this.nonterminal_rules.put("_gen10", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("step", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("task_attr_value", new ArrayList()); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(0), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen0 'rbrace' -> CompositeTask( body=$3, name=$1 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "_gen9 := 'comma' step_output _gen9"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(1), rule); - rule = "_gen1 := step_name"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "_gen4 := task_attrs"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(2), rule); - rule = "_gen8 := ε"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(3), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; - this.nonterminal_rules.get("task_attr").add(rule); + rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); this.rules.put(new Integer(4), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); - this.rules.put(new Integer(5), rule); - rule = "composite_task_entity := composite_task"; - this.nonterminal_rules.get("composite_task_entity").add(rule); - this.rules.put(new Integer(6), rule); rule = "_gen4 := ε"; this.nonterminal_rules.get("_gen4").add(rule); + this.rules.put(new Integer(5), rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; + this.nonterminal_rules.get("step_output").add(rule); + this.rules.put(new Integer(6), rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(7), rule); - rule = "task_attr_value := 'number'"; + rule = "task_attr_value := 'string'"; this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(8), rule); - rule = "_gen9 := variable_member"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "_gen7 := ε"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(9), rule); - rule = "_gen8 := 'comma' step_output _gen8"; - this.nonterminal_rules.get("_gen8").add(rule); - this.rules.put(new Integer(10), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen0 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; - this.nonterminal_rules.get("for_loop").add(rule); - this.rules.put(new Integer(11), rule); rule = "step_name := 'as' 'identifier' -> $1"; this.nonterminal_rules.get("step_name").add(rule); - this.rules.put(new Integer(12), rule); - rule = "composite_task_entity := composite_task"; + this.rules.put(new Integer(10), rule); + rule = "composite_task_entity := step"; this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(11), rule); + rule = "task_attr_value := 'identifier'"; + this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(12), rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(13), rule); - rule = "_gen2 := ε"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(14), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "_gen5 := ε"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(15), rule); - rule = "step_attr := step_output_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(16), rule); - rule = "task_attrs := 'lsquare' _gen4 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(17), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + this.nonterminal_rules.get("task_attr").add(rule); this.rules.put(new Integer(18), rule); - rule = "task_identifier := 'identifier' _gen3 -> Task( attributes=$1, name=$0 )"; - this.nonterminal_rules.get("task_identifier").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(19), rule); - rule = "_gen5 := ε"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(20), rule); - rule = "_gen6 := ε"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(21), rule); - rule = "_gen6 := 'comma' step_input _gen6"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "_gen2 := step_name"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(22), rule); - rule = "step_output_list := 'output' 'colon' _gen7 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); this.rules.put(new Integer(23), rule); - rule = "variable_member := 'dot' 'identifier' -> $1"; - this.nonterminal_rules.get("variable_member").add(rule); + rule = "_gen0 := wdl_entity _gen0"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(24), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "_gen6 := ε"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(25), rule); - rule = "_gen3 := ε"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, name=$2, task=$1 )"; + this.nonterminal_rules.get("step").add(rule); this.rules.put(new Integer(26), rule); - rule = "composite_task := _gen0"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(27), rule); - rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; - this.nonterminal_rules.get("step_input").add(rule); + rule = "_gen5 := task_attr _gen5"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(28), rule); - rule = "_gen2 := step_attr _gen2"; + rule = "_gen2 := ε"; this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(29), rule); - rule = "_gen5 := step_input _gen6"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); this.rules.put(new Integer(30), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(31), rule); - rule = "task_attr_value := 'identifier'"; - this.nonterminal_rules.get("task_attr_value").add(rule); - this.rules.put(new Integer(32), rule); - rule = "composite_task_entity := step"; + rule = "composite_task_entity := composite_task"; this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(32), rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(33), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen7 := 'comma' step_input _gen7"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(34), rule); - rule = "step := 'step' task_identifier _gen1 'lbrace' _gen2 'rbrace' -> Step( body=$4, task=$1, name=$2 )"; - this.nonterminal_rules.get("step").add(rule); + rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(35), rule); - rule = "_gen4 := task_attr _gen4"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "_gen3 := step_attr _gen3"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(36), rule); - rule = "variable := 'identifier' _gen9 -> Variable( member=$1, name=$0 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "_gen6 := step_input _gen7"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(37), rule); - rule = "_gen7 := step_output _gen8"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(38), rule); - rule = "_gen0 := composite_task_entity _gen0"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "_gen10 := variable_member"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(39), rule); - rule = "_gen7 := ε"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(40), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen8 := step_output _gen9"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(41), rule); - rule = "step_input_list := 'input' 'colon' _gen5 'semi' -> StepInputList( inputs=$2 )"; - this.nonterminal_rules.get("step_input_list").add(rule); + rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(42), rule); - this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); - this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); + this.rules.put(new Integer(43), rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); + this.rules.put(new Integer(44), rule); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); - this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); + this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); + this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_STRING, TerminalId.TERMINAL_NUMBER }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("wdl", new TerminalId[] { }); this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); + this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); + this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); } public TerminalMap getTerminalMap() { return new CompositeTaskTerminalMap(TerminalId.values()); @@ -315,7 +333,7 @@ public ParseTree parse(TokenStream tokens) throws SyntaxError { this.tokens = tokens; this.tokens.setSyntaxErrorFormatter(this.syntaxErrorFormatter); this.tokens.setTerminalMap(this.getTerminalMap()); - ParseTree tree = this.parse_composite_task(); + ParseTree tree = this.parse_wdl(); if (this.tokens.current() != null) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); throw new SyntaxError(this.syntaxErrorFormatter.excess_tokens(stack[1].getMethodName(), this.tokens.current())); @@ -326,23 +344,23 @@ private boolean isTerminal(TerminalId terminal) { return (0 <= terminal.id() && terminal.id() <= 21); } private boolean isNonTerminal(TerminalId terminal) { - return (22 <= terminal.id() && terminal.id() <= 47); + return (22 <= terminal.id() && terminal.id() <= 50); } private boolean isTerminal(int terminal) { return (0 <= terminal && terminal <= 21); } private boolean isNonTerminal(int terminal) { - return (22 <= terminal && terminal <= 47); + return (22 <= terminal && terminal <= 50); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "_gen1")); + ParseTree tree = new ParseTree( new NonTerminal(22, "_gen4")); tree.setList(null); if ( current != null ) { - if (current.getId() == 9) { + if (current.getId() == 13) { return tree; } } @@ -351,355 +369,409 @@ private ParseTree parse__gen1() throws SyntaxError { } if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen7")); + ParseTree tree = new ParseTree( new NonTerminal(23, "_gen6")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 0) { + if (current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 38) { + if (rule == 37) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen3")); + ParseTree tree = new ParseTree( new NonTerminal(24, "task_attr")); tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") + )); + } + if (rule == 18) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("value", 2); + parameters.put("key", 0); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(18)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(18)); + tree.add(next); + subtree = this.parse_task_attr_value(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("task_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr", + current, + Arrays.asList(this.first.get("task_attr")), + this.rules.get(18) + )); + } + private ParseTree parse__gen7() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "_gen7")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 8) { + if (current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 0) { + if (rule == 34) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(34)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "step_name")); + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "variable")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_name", - Arrays.asList(this.first.get("step_name")), - this.nonterminal_rules.get("step_name") + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") )); } - if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(12)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(12)); + if (rule == 35) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("member", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(35)); tree.add(next); + subtree = this.parse__gen10(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_name")); + List terminals = Arrays.asList(this.first.get("variable")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_name", + "variable", current, - Arrays.asList(this.first.get("step_name")), - this.rules.get(12) + Arrays.asList(this.first.get("variable")), + this.rules.get(35) )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "step_output")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "_gen5")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 21) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 28) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen5(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_for_loop() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") )); } - if (rule == 31) { + if (rule == 19) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(31)); + parameters.put("body", 7); + parameters.put("item", 2); + parameters.put("collection", 4); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(19)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(31)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(19)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(31)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(19)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(31)); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(19)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(31)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(19)); tree.add(next); - subtree = this.parse_variable(); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(19)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(19)); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(19)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + List terminals = Arrays.asList(this.first.get("for_loop")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "for_loop", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(31) + Arrays.asList(this.first.get("for_loop")), + this.rules.get(19) )); } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "composite_task_entity")); - tree.setList(null); - if (current == null) { - return tree; - } - if (rule == 6) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); - tree.add( subtree); - return tree; + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "_gen1")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } } - else if (rule == 13) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); - tree.add( subtree); + if (current == null) { return tree; } - else if (rule == 33) { + if (rule == 21) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - return tree; - } - else if (rule == 41) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task_entity", - current, - Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(41) - )); + return tree; } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "step")); + int rule = current != null ? this.table[8][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "step_output_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step", - Arrays.asList(this.first.get("step")), - this.nonterminal_rules.get("step") + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") )); } - if (rule == 35) { + if (rule == 40) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 4); - parameters.put("task", 1); - parameters.put("name", 2); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(35)); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(40)); tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(35)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(40)); tree.add(next); - subtree = this.parse__gen2(); + subtree = this.parse__gen8(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(35)); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(40)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step")); + List terminals = Arrays.asList(this.first.get("step_output_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step", + "step_output_list", current, - Arrays.asList(this.first.get("step")), - this.rules.get(35) + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(40) )); } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "step_input")); - tree.setList(null); + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen3")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == 9) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") - )); + return tree; } - if (rule == 28) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(28)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(28)); - tree.add(next); - subtree = this.parse_variable(); + if (rule == 36) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_attr(); + tree.add( subtree); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", - current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(28) - )); + return tree; } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "step_attr")); + int rule = current != null ? this.table[10][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "composite_task_entity")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_attr", - Arrays.asList(this.first.get("step_attr")), - this.nonterminal_rules.get("step_attr") + "composite_task_entity", + Arrays.asList(this.first.get("composite_task_entity")), + this.nonterminal_rules.get("composite_task_entity") )); } - if (rule == 16) { + if (rule == 11) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + subtree = this.parse_step(); tree.add( subtree); return tree; } - else if (rule == 34) { + else if (rule == 20) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); + subtree = this.parse_for_loop(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_attr")); + else if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task_entity")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_attr", + "composite_task_entity", current, - Arrays.asList(this.first.get("step_attr")), - this.rules.get(34) + Arrays.asList(this.first.get("composite_task_entity")), + this.rules.get(32) )); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen5")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 0) { - return tree; - } - } + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(33, "wdl")); + tree.setList(null); if (current == null) { return tree; } if (rule == 30) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen6(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("wdl")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "wdl", + current, + Arrays.asList(this.first.get("wdl")), + this.rules.get(30) + )); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "_gen6")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 0) { - return tree; - } - } + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "variable_member")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") + )); } - if (rule == 22) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen6", this.rules.get(22)); + if (rule == 0) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(0)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(0)); tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen6(); - tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("variable_member")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable_member", + current, + Arrays.asList(this.first.get("variable_member")), + this.rules.get(0) + )); } private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "_gen9")); - tree.setList(null); + int rule = current != null ? this.table[13][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "_gen9")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == 21 || current.getId() == 0) { + if (current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 9) { + if (rule == 1) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(1)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } @@ -709,8 +781,8 @@ private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "task_identifier")); + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(36, "task_identifier")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -719,14 +791,14 @@ private ParseTree parse_task_identifier() throws SyntaxError { this.nonterminal_rules.get("task_identifier") )); } - if (rule == 19) { + if (rule == 42) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("attributes", 1); parameters.put("name", 0); + parameters.put("attributes", 1); tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(19)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(42)); tree.add(next); - subtree = this.parse__gen3(); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } @@ -735,441 +807,460 @@ private ParseTree parse_task_identifier() throws SyntaxError { "task_identifier", current, Arrays.asList(this.first.get("task_identifier")), - this.rules.get(19) + this.rules.get(42) )); } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr_value")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "wdl_entity")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr_value", - Arrays.asList(this.first.get("task_attr_value")), - this.nonterminal_rules.get("task_attr_value") + "wdl_entity", + Arrays.asList(this.first.get("wdl_entity")), + this.nonterminal_rules.get("wdl_entity") )); } - if (rule == 8) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(8)); - tree.add(next); - return tree; - } - else if (rule == 18) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(18)); - tree.add(next); - return tree; - } - else if (rule == 32) { + if (rule == 23) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(32)); - tree.add(next); + subtree = this.parse_composite_task(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr_value")); + List terminals = Arrays.asList(this.first.get("wdl_entity")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr_value", + "wdl_entity", current, - Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(32) + Arrays.asList(this.first.get("wdl_entity")), + this.rules.get(23) )); } private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "composite_task")); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "composite_task")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") + )); } - if (rule == 1) { + if (rule == 33) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("body", 3); parameters.put("name", 1); tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(1)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(33)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(1)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(33)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(33)); tree.add(next); - subtree = this.parse__gen0(); + subtree = this.parse__gen1(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(1)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(33)); tree.add(next); return tree; } - else if (rule == 27) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); - tree.add( subtree); - return tree; - } List terminals = Arrays.asList(this.first.get("composite_task")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( "composite_task", current, Arrays.asList(this.first.get("composite_task")), - this.rules.get(27) + this.rules.get(33) )); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "_gen0")); - tree.setList("nlist"); + int rule = current != null ? this.table[17][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "step_input")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") + )); + } + if (rule == 43) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(43)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(43)); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_input")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_input", + current, + Arrays.asList(this.first.get("step_input")), + this.rules.get(43) + )); + } + private ParseTree parse__gen8() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(40, "_gen8")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == -1 || current.getId() == 18 || current.getId() == 5 || current.getId() == 6 || current.getId() == 15) { + if (current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 39) { + if (rule == 41) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); + subtree = this.parse_step_output(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "task_attr")); + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "step_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") - )); - } - if (rule == 4) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(4)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(4)); - tree.add(next); - subtree = this.parse_task_attr_value(); + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") + )); + } + if (rule == 7) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input_list(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr")); + else if (rule == 13) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", + "step_attr", current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(4) + Arrays.asList(this.first.get("step_attr")), + this.rules.get(13) )); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "variable")); + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "step_name")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable", - Arrays.asList(this.first.get("variable")), - this.nonterminal_rules.get("variable") + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") )); } - if (rule == 37) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("member", 1); - parameters.put("name", 0); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(37)); + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(10)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(10)); tree.add(next); - subtree = this.parse__gen9(); - tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable")); + List terminals = Arrays.asList(this.first.get("step_name")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable", + "step_name", current, - Arrays.asList(this.first.get("variable")), - this.rules.get(37) + Arrays.asList(this.first.get("step_name")), + this.rules.get(10) )); } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "task_attrs")); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attrs", - Arrays.asList(this.first.get("task_attrs")), - this.nonterminal_rules.get("task_attrs") + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") )); } - if (rule == 17) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(17)); + if (rule == 6) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("as", 5); + parameters.put("file", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(6)); tree.add(next); - subtree = this.parse__gen4(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(6)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(6)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(6)); tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(6)); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attrs")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attrs", + "step_output", current, - Arrays.asList(this.first.get("task_attrs")), - this.rules.get(17) + Arrays.asList(this.first.get("step_output")), + this.rules.get(6) )); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "_gen4")); - tree.setList("nlist"); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "_gen2")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 19) { + if (current.getId() == 0) { return tree; } } if (current == null) { return tree; } - if (rule == 36) { + if (rule == 22) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); - tree.add( subtree); - subtree = this.parse__gen4(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "_gen2")); - tree.setList("nlist"); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "step_input_list")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") + )); + } + if (rule == 17) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(17)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(17)); + tree.add(next); + subtree = this.parse__gen6(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(17)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_input_list")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_input_list", + current, + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(17) + )); + } + private ParseTree parse__gen10() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "_gen10")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 6) { + if (current.getId() == 19 || current.getId() == 15) { return tree; } } if (current == null) { return tree; } - if (rule == 29) { + if (rule == 39) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); - tree.add( subtree); - subtree = this.parse__gen2(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "_gen8")); - tree.setList("slist"); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen0")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 0) { + if (current.getId() == -1) { return tree; } } if (current == null) { return tree; } - if (rule == 10) { + if (rule == 24) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen8", this.rules.get(10)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); + subtree = this.parse_wdl_entity(); tree.add( subtree); - subtree = this.parse__gen8(); + subtree = this.parse__gen0(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "step_input_list")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "step")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") )); } - if (rule == 42) { + if (rule == 26) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(42)); + parameters.put("body", 4); + parameters.put("name", 2); + parameters.put("task", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(26)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(42)); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(26)); tree.add(next); - subtree = this.parse__gen5(); + subtree = this.parse__gen3(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(42)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(26)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); + List terminals = Arrays.asList(this.first.get("step")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", + "step", current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(42) + Arrays.asList(this.first.get("step")), + this.rules.get(26) )); } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "variable_member")); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "task_attrs")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") )); } - if (rule == 24) { + if (rule == 4) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(24)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(4)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(24)); + subtree = this.parse__gen5(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(4)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("variable_member")); + List terminals = Arrays.asList(this.first.get("task_attrs")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", + "task_attrs", current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(24) + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(4) )); } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "for_loop")); + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "for_loop", - Arrays.asList(this.first.get("for_loop")), - this.nonterminal_rules.get("for_loop") + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 11) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(11)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(11)); - tree.add(next); - subtree = this.parse__gen0(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(11)); + if (rule == 8) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(8)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("for_loop")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "for_loop", - current, - Arrays.asList(this.first.get("for_loop")), - this.rules.get(11) - )); - } - private ParseTree parse_step_output_list() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "step_output_list")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") - )); - } - if (rule == 23) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(23)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(23)); + else if (rule == 12) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(12)); tree.add(next); - subtree = this.parse__gen7(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(23)); + return tree; + } + else if (rule == 16) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(16)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_list")); + List terminals = Arrays.asList(this.first.get("task_attr_value")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", + "task_attr_value", current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(23) + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(16) )); } } From 800b9e138fca480b0a03e073dbda1d912e330231 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 11 Dec 2012 10:02:03 -0500 Subject: [PATCH 107/140] Adding support for 'into' as well as 'as' for output variables --- README.md | 2 +- grammars/composite_task.zgr | 4 +- .../compositetask/CompositeTask.java | 19 +- .../compositetask/CompositeTaskStepOutput.java | 8 +- .../org/broadinstitute/compositetask/Lexer.java | 1 + .../broadinstitute/parser/CompositeTaskParser.java | 1417 ++++++++++---------- 6 files changed, 760 insertions(+), 691 deletions(-) diff --git a/README.md b/README.md index e271b88..5717b84 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Generating the parser code Use the Hermes parser generator (http://github.com/scottfrazer/hermes). From the root of this repository, run: ``` -$ hermes generate grammars/wdl.zgr --directory=src/main/java/org/broadinstitute/compositetask --language=java --java-package=org.broadinstitute.compositetask +$ hermes generate grammars/composite_task.zgr --directory=src/main/java/org/broadinstitute/compositetask --language=java --java-package=org.broadinstitute.compositetask ``` Or, run the Ant target `generate-parser` which will run the command above: diff --git a/grammars/composite_task.zgr b/grammars/composite_task.zgr index a58793d..288c5b7 100644 --- a/grammars/composite_task.zgr +++ b/grammars/composite_task.zgr @@ -17,7 +17,9 @@ "step_input_list := 'input' + 'colon' + list(step_input, 'comma') + 'semi' -> StepInputList( inputs=$2 )", "step_input := 'identifier' + 'assign' + variable -> StepInput(parameter=$0, value=$2)", "step_output_list := 'output' + 'colon' + list(step_output, 'comma') + 'semi' -> StepOutputList( outputs=$2 )", - "step_output := 'file' + 'lparen' + 'string' + 'rparen' + 'as' + variable -> StepFileOutput( file=$2, as=$5 )", + "step_output := 'file' + 'lparen' + 'string' + 'rparen' + step_output_location -> StepFileOutput( file=$2, var=$4 )", + "step_output_location := 'as' + variable -> OutputVariable( var=$1 )", + "step_output_location := 'into' + variable -> OutputListAppend( var=$1 )", "variable := 'identifier' + optional(variable_member) -> Variable(name=$0, member=$1)", "variable_member := 'dot' + 'identifier -> $1" ] diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 0a0b24b..f9757c6 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -164,13 +164,22 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { for ( AstNode output_node : output_list ) { Ast output = (Ast) output_node; Terminal filepath = (Terminal) output.getAttribute("file"); - CompositeTaskVariable variable = ast_to_variable((Ast) output.getAttribute("as")); + Ast output_var = (Ast) output.getAttribute("var"); + + CompositeTaskVariable variable = ast_to_variable((Ast) output_var.getAttribute("var")); + Terminal variable_terminal = (Terminal) ((Ast) output.getAttribute("var")).getAttribute("name"); + String method = null; + + if ( output_var.getName().equals("OutputVariable") ) { + method = "assign"; + } else if ( output_var.getName().equals("OutputListAppend") ) { + method = "append"; + } - Terminal var_terminal = (Terminal) ((Ast) output.getAttribute("as")).getAttribute("name"); if (this.output_variables.containsKey(variable)) { - throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_variable(var_terminal, this.output_variables.get(variable))); + throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_variable(variable_terminal, this.output_variables.get(variable))); } else { - this.output_variables.put(variable, var_terminal); + this.output_variables.put(variable, variable_terminal); } if (this.output_files.containsKey(filepath.getSourceString())) { @@ -179,7 +188,7 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { this.output_files.put(filepath.getSourceString(), filepath); } - step_outputs.add( new CompositeTaskStepOutput("File", filepath.getSourceString(), variable) ); + step_outputs.add( new CompositeTaskStepOutput("File", method, filepath.getSourceString(), variable) ); } } } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java index 78b2f72..5c4ec60 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java @@ -6,11 +6,13 @@ public class CompositeTaskStepOutput { private String type; + private String method; private String path; private CompositeTaskVariable variable; - public CompositeTaskStepOutput(String type, String path, CompositeTaskVariable variable) { + public CompositeTaskStepOutput(String type, String method, String path, CompositeTaskVariable variable) { this.type = type; + this.method = method; this.path = path; this.variable = variable; } @@ -23,6 +25,10 @@ public String getPath() { return this.path; } + public String getMethod() { + return this.method; + } + public String getType() { return this.type; } diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index e855bd2..01e1957 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -62,6 +62,7 @@ LexerMatch match(SourceCode source) { this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) ); + this.regex.add( new TokenLexer(Pattern.compile("^into(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INTO) ); this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_IN) ); this.regex.add( new TokenLexer(Pattern.compile("^\\."), CompositeTaskParser.TerminalId.TERMINAL_DOT) ); this.regex.add( new TokenLexer(Pattern.compile("^,"), CompositeTaskParser.TerminalId.TERMINAL_COMMA) ); diff --git a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java index a843193..43a7ffe 100644 --- a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java +++ b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java @@ -14,59 +14,61 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 2, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, 34, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15 }, - { -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 21, 21, -1, -1, -1, -1, -1, -1, 14, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 36, 38, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, 20, 32, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, 1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, 41, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1 }, - { 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, 39, -1, 31, -1, -1 }, - { -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 12, 8, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 46, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 37, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, 7, -1, 8, -1, -1, -1, -1 }, + { -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 35, 20, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24 }, + { -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, 36, -1, -1, -1, -1 }, + { -1, -1, 0, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_LBRACE(0, "lbrace"), - TERMINAL_FOR(1, "for"), - TERMINAL_COMPOSITE_TASK(2, "composite_task"), - TERMINAL_LPAREN(3, "lparen"), - TERMINAL_IN(4, "in"), - TERMINAL_ASSIGN(5, "assign"), - TERMINAL_IDENTIFIER(6, "identifier"), - TERMINAL_STRING(7, "string"), - TERMINAL_OUTPUT(8, "output"), - TERMINAL_RBRACE(9, "rbrace"), - TERMINAL_STEP(10, "step"), - TERMINAL_INPUT(11, "input"), - TERMINAL_COLON(12, "colon"), - TERMINAL_AS(13, "as"), - TERMINAL_NUMBER(14, "number"), - TERMINAL_SEMI(15, "semi"), - TERMINAL_LSQUARE(16, "lsquare"), - TERMINAL_DOT(17, "dot"), - TERMINAL_FILE(18, "file"), - TERMINAL_COMMA(19, "comma"), - TERMINAL_RPAREN(20, "rparen"), - TERMINAL_RSQUARE(21, "rsquare"); + TERMINAL_FOR(0, "for"), + TERMINAL_RSQUARE(1, "rsquare"), + TERMINAL_AS(2, "as"), + TERMINAL_IN(3, "in"), + TERMINAL_ASSIGN(4, "assign"), + TERMINAL_RPAREN(5, "rparen"), + TERMINAL_LSQUARE(6, "lsquare"), + TERMINAL_OUTPUT(7, "output"), + TERMINAL_INPUT(8, "input"), + TERMINAL_FILE(9, "file"), + TERMINAL_COMMA(10, "comma"), + TERMINAL_STEP(11, "step"), + TERMINAL_COMPOSITE_TASK(12, "composite_task"), + TERMINAL_IDENTIFIER(13, "identifier"), + TERMINAL_STRING(14, "string"), + TERMINAL_NUMBER(15, "number"), + TERMINAL_DOT(16, "dot"), + TERMINAL_COLON(17, "colon"), + TERMINAL_SEMI(18, "semi"), + TERMINAL_LPAREN(19, "lparen"), + TERMINAL_INTO(20, "into"), + TERMINAL_LBRACE(21, "lbrace"), + TERMINAL_RBRACE(22, "rbrace"); private final int id; private final String string; TerminalId(int id, String string) { @@ -103,228 +105,237 @@ public CompositeTaskParser(SyntaxErrorFormatter syntaxErrorFormatter) { this.rules = new HashMap(); ArrayList list; String rule; - this.nonterminal_rules.put("_gen4", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); - this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("_gen7", new ArrayList()); - this.nonterminal_rules.put("variable", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); - this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("_gen1", new ArrayList()); - this.nonterminal_rules.put("step_output_list", new ArrayList()); + this.nonterminal_rules.put("step_name", new ArrayList()); this.nonterminal_rules.put("_gen3", new ArrayList()); - this.nonterminal_rules.put("composite_task_entity", new ArrayList()); - this.nonterminal_rules.put("wdl", new ArrayList()); - this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("_gen9", new ArrayList()); - this.nonterminal_rules.put("task_identifier", new ArrayList()); - this.nonterminal_rules.put("wdl_entity", new ArrayList()); - this.nonterminal_rules.put("composite_task", new ArrayList()); this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("_gen8", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); this.nonterminal_rules.put("step_attr", new ArrayList()); - this.nonterminal_rules.put("step_name", new ArrayList()); - this.nonterminal_rules.put("step_output", new ArrayList()); - this.nonterminal_rules.put("_gen2", new ArrayList()); - this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("variable", new ArrayList()); this.nonterminal_rules.put("_gen10", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("step_output_location", new ArrayList()); + this.nonterminal_rules.put("task_attr_value", new ArrayList()); + this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("step_input_list", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); + this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); this.nonterminal_rules.put("step", new ArrayList()); + this.nonterminal_rules.put("_gen9", new ArrayList()); + this.nonterminal_rules.put("_gen8", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); this.nonterminal_rules.put("task_attrs", new ArrayList()); - this.nonterminal_rules.put("task_attr_value", new ArrayList()); - rule = "variable_member := 'dot' 'identifier' -> $1"; - this.nonterminal_rules.get("variable_member").add(rule); + this.nonterminal_rules.put("task_attr", new ArrayList()); + this.nonterminal_rules.put("composite_task_entity", new ArrayList()); + this.nonterminal_rules.put("for_loop", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen6", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(0), rule); - rule = "_gen9 := 'comma' step_output _gen9"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(1), rule); - rule = "_gen4 := task_attrs"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); this.rules.put(new Integer(2), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(3), rule); - rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "step_output_location := 'into' variable -> OutputListAppend( var=$1 )"; + this.nonterminal_rules.get("step_output_location").add(rule); this.rules.put(new Integer(4), rule); - rule = "_gen4 := ε"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( task=$1, name=$2, body=$4 )"; + this.nonterminal_rules.get("step").add(rule); this.rules.put(new Integer(5), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' 'as' variable -> StepFileOutput( as=$5, file=$2 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(6), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen10 := variable_member"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(7), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(8), rule); - rule = "_gen7 := ε"; - this.nonterminal_rules.get("_gen7").add(rule); - this.rules.put(new Integer(9), rule); - rule = "step_name := 'as' 'identifier' -> $1"; - this.nonterminal_rules.get("step_name").add(rule); - this.rules.put(new Integer(10), rule); - rule = "composite_task_entity := step"; + rule = "composite_task_entity := composite_task"; this.nonterminal_rules.get("composite_task_entity").add(rule); - this.rules.put(new Integer(11), rule); + this.rules.put(new Integer(9), rule); rule = "task_attr_value := 'identifier'"; this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(10), rule); + rule = "_gen5 := ε"; + this.nonterminal_rules.get("_gen5").add(rule); + this.rules.put(new Integer(11), rule); + rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(12), rule); - rule = "step_attr := step_output_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen8 := step_output _gen9"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(13), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(14), rule); - rule = "_gen5 := ε"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "step_output_location := 'as' variable -> OutputVariable( var=$1 )"; + this.nonterminal_rules.get("step_output_location").add(rule); this.rules.put(new Integer(15), rule); - rule = "task_attr_value := 'number'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); this.rules.put(new Integer(16), rule); - rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; - this.nonterminal_rules.get("step_input_list").add(rule); + rule = "_gen9 := 'comma' step_output _gen9"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(17), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( value=$2, key=$0 )"; + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( key=$0, value=$2 )"; this.nonterminal_rules.get("task_attr").add(rule); this.rules.put(new Integer(18), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( body=$7, item=$2, collection=$4 )"; - this.nonterminal_rules.get("for_loop").add(rule); + rule = "_gen2 := step_name"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(19), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(20), rule); - rule = "_gen1 := composite_task_entity _gen1"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(21), rule); - rule = "_gen2 := step_name"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "step_output := 'file' 'lparen' 'string' 'rparen' step_output_location -> StepFileOutput( file=$2, var=$4 )"; + this.nonterminal_rules.get("step_output").add(rule); this.rules.put(new Integer(22), rule); - rule = "wdl_entity := composite_task"; - this.nonterminal_rules.get("wdl_entity").add(rule); + rule = "_gen2 := ε"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(23), rule); - rule = "_gen0 := wdl_entity _gen0"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "_gen1 := ε"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(24), rule); - rule = "_gen6 := ε"; - this.nonterminal_rules.get("_gen6").add(rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( name=$1, body=$3 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(25), rule); - rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( body=$4, name=$2, task=$1 )"; - this.nonterminal_rules.get("step").add(rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(26), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "composite_task_entity := step"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(27), rule); - rule = "_gen5 := task_attr _gen5"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "_gen6 := step_input _gen7"; + this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(28), rule); - rule = "_gen2 := ε"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "_gen4 := task_attrs"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(29), rule); - rule = "wdl := _gen0"; - this.nonterminal_rules.get("wdl").add(rule); + rule = "_gen0 := wdl_entity _gen0"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(30), rule); - rule = "_gen10 := ε"; - this.nonterminal_rules.get("_gen10").add(rule); - this.rules.put(new Integer(31), rule); - rule = "composite_task_entity := composite_task"; + rule = "composite_task_entity := for_loop"; this.nonterminal_rules.get("composite_task_entity").add(rule); + this.rules.put(new Integer(31), rule); + rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(32), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( body=$3, name=$1 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(33), rule); - rule = "_gen7 := 'comma' step_input _gen7"; + rule = "_gen7 := ε"; this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(34), rule); - rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(35), rule); - rule = "_gen3 := step_attr _gen3"; - this.nonterminal_rules.get("_gen3").add(rule); - this.rules.put(new Integer(36), rule); - rule = "_gen6 := step_input _gen7"; + rule = "_gen6 := ε"; this.nonterminal_rules.get("_gen6").add(rule); + this.rules.put(new Integer(36), rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(37), rule); - rule = "_gen3 := ε"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); this.rules.put(new Integer(38), rule); - rule = "_gen10 := variable_member"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "_gen7 := 'comma' step_input _gen7"; + this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(39), rule); - rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); this.rules.put(new Integer(40), rule); - rule = "_gen8 := step_output _gen9"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(41), rule); - rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )"; - this.nonterminal_rules.get("task_identifier").add(rule); + rule = "_gen5 := task_attr _gen5"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(42), rule); - rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; - this.nonterminal_rules.get("step_input").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(43), rule); - rule = "_gen8 := ε"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(44), rule); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); + this.rules.put(new Integer(45), rule); + rule = "_gen3 := step_attr _gen3"; + this.nonterminal_rules.get("_gen3").add(rule); + this.rules.put(new Integer(46), rule); + this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); - this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.first.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_AS, TerminalId.TERMINAL_INTO }); + this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_INPUT }); - this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); - this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); + this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_STRING, TerminalId.TERMINAL_NUMBER }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); + this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); + this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("wdl", new TerminalId[] { }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("wdl", new TerminalId[] { }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); - this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT }); - this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("_gen0", new TerminalId[] { }); - this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("_gen0", new TerminalId[] { }); } public TerminalMap getTerminalMap() { return new CompositeTaskTerminalMap(TerminalId.values()); @@ -341,134 +352,177 @@ public ParseTree parse(TokenStream tokens) throws SyntaxError { return tree; } private boolean isTerminal(TerminalId terminal) { - return (0 <= terminal.id() && terminal.id() <= 21); + return (0 <= terminal.id() && terminal.id() <= 22); } private boolean isNonTerminal(TerminalId terminal) { - return (22 <= terminal.id() && terminal.id() <= 50); + return (23 <= terminal.id() && terminal.id() <= 52); } private boolean isTerminal(int terminal) { - return (0 <= terminal && terminal <= 21); + return (0 <= terminal && terminal <= 22); } private boolean isNonTerminal(int terminal) { - return (22 <= terminal && terminal <= 50); + return (23 <= terminal && terminal <= 52); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse_step_name() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(22, "_gen4")); + ParseTree tree = new ParseTree( new NonTerminal(23, "step_name")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 13) { - return tree; - } - } if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_name", + Arrays.asList(this.first.get("step_name")), + this.nonterminal_rules.get("step_name") + )); } - if (rule == 2) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); - tree.add( subtree); + if (rule == 40) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(40)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(40)); + tree.add(next); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("step_name")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_name", + current, + Arrays.asList(this.first.get("step_name")), + this.rules.get(40) + )); } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "_gen6")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen3")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 15) { + if (current.getId() == 22) { return tree; } } if (current == null) { return tree; } - if (rule == 37) { + if (rule == 46) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen7(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "task_attr")); + ParseTree tree = new ParseTree( new NonTerminal(25, "step_input")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") )); } - if (rule == 18) { + if (rule == 38) { LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("parameter", 0); parameters.put("value", 2); - parameters.put("key", 0); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(18)); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(38)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(18)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(38)); tree.add(next); - subtree = this.parse_task_attr_value(); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr")); + List terminals = Arrays.asList(this.first.get("step_input")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", + "step_input", current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(18) + Arrays.asList(this.first.get("step_input")), + this.rules.get(38) )); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse_variable_member() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "_gen7")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 15) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(26, "variable_member")); + tree.setList(null); if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") + )); + } + if (rule == 3) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(3)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(3)); + tree.add(next); return tree; } - if (rule == 34) { + List terminals = Arrays.asList(this.first.get("variable_member")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable_member", + current, + Arrays.asList(this.first.get("variable_member")), + this.rules.get(3) + )); + } + private ParseTree parse_step_attr() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[4][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "step_attr")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") + )); + } + if (rule == 26) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(34)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); + subtree = this.parse_step_input_list(); tree.add( subtree); - subtree = this.parse__gen7(); + return tree; + } + else if (rule == 37) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("step_attr")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_attr", + current, + Arrays.asList(this.first.get("step_attr")), + this.rules.get(37) + )); } private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "variable")); + int rule = current != null ? this.table[5][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(28, "variable")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -477,12 +531,12 @@ private ParseTree parse_variable() throws SyntaxError { this.nonterminal_rules.get("variable") )); } - if (rule == 35) { + if (rule == 12) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("name", 0); parameters.put("member", 1); tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(35)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(12)); tree.add(next); subtree = this.parse__gen10(); tree.add( subtree); @@ -493,219 +547,153 @@ private ParseTree parse_variable() throws SyntaxError { "variable", current, Arrays.asList(this.first.get("variable")), - this.rules.get(35) + this.rules.get(12) )); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "_gen5")); - tree.setList("nlist"); + int rule = current != null ? this.table[6][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(29, "_gen10")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 21) { + if (current.getId() == 10 || current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 28) { + if (rule == 7) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); - tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_for_loop() throws SyntaxError { + private ParseTree parse_step_output_location() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "for_loop")); + int rule = current != null ? this.table[7][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(30, "step_output_location")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "for_loop", - Arrays.asList(this.first.get("for_loop")), - this.nonterminal_rules.get("for_loop") + "step_output_location", + Arrays.asList(this.first.get("step_output_location")), + this.nonterminal_rules.get("step_output_location") )); } - if (rule == 19) { + if (rule == 4) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 7); - parameters.put("item", 2); - parameters.put("collection", 4); - tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(19)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(19)); + parameters.put("var", 1); + tree.setAstTransformation(new AstTransformNodeCreator("OutputListAppend", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INTO, "step_output_location", this.rules.get(4)); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse_variable(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(19)); + return tree; + } + else if (rule == 15) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("var", 1); + tree.setAstTransformation(new AstTransformNodeCreator("OutputVariable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output_location", this.rules.get(15)); tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("for_loop")); + List terminals = Arrays.asList(this.first.get("step_output_location")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "for_loop", + "step_output_location", current, - Arrays.asList(this.first.get("for_loop")), - this.rules.get(19) + Arrays.asList(this.first.get("step_output_location")), + this.rules.get(15) )); } - private ParseTree parse__gen1() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "_gen1")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 9) { - return tree; - } - } - if (current == null) { - return tree; - } - if (rule == 21) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); - tree.add( subtree); - subtree = this.parse__gen1(); - tree.add( subtree); - return tree; - } - return tree; - } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "step_output_list")); + ParseTree tree = new ParseTree( new NonTerminal(31, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 40) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(40)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(40)); - tree.add(next); - subtree = this.parse__gen8(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(40)); + if (rule == 10) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(10)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_list")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", - current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(40) - )); - } - private ParseTree parse__gen3() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "_gen3")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 9) { - return tree; - } - } - if (current == null) { + else if (rule == 20) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(20)); + tree.add(next); return tree; } - if (rule == 36) { + else if (rule == 35) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); - tree.add( subtree); - subtree = this.parse__gen3(); - tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(35)); + tree.add(next); return tree; } - return tree; - } - private ParseTree parse_composite_task_entity() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "composite_task_entity")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task_entity", - Arrays.asList(this.first.get("composite_task_entity")), - this.nonterminal_rules.get("composite_task_entity") - )); + List terminals = Arrays.asList(this.first.get("task_attr_value")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attr_value", + current, + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(35) + )); + } + private ParseTree parse__gen7() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[9][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(32, "_gen7")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 18) { + return tree; + } } - if (rule == 11) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); - tree.add( subtree); + if (current == null) { return tree; } - else if (rule == 20) { + if (rule == 39) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(39)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); tree.add( subtree); - return tree; - } - else if (rule == 32) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task_entity", - current, - Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(32) - )); + return tree; } private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[11][current.getId()] : -1; + int rule = current != null ? this.table[10][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(33, "wdl")); tree.setList(null); if (current == null) { return tree; } - if (rule == 30) { + if (rule == 16) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse__gen0(); tree.add( subtree); @@ -716,72 +704,78 @@ private ParseTree parse_wdl() throws SyntaxError { "wdl", current, Arrays.asList(this.first.get("wdl")), - this.rules.get(30) + this.rules.get(16) )); } - private ParseTree parse_variable_member() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "variable_member")); + int rule = current != null ? this.table[11][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(34, "step_input_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") )); } - if (rule == 0) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(0)); + if (rule == 41) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(41)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(41)); + tree.add(next); + subtree = this.parse__gen6(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(41)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("variable_member")); + List terminals = Arrays.asList(this.first.get("step_input_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", + "step_input_list", current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(0) + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(41) )); } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse_wdl_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "_gen9")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 15) { - return tree; - } - } + int rule = current != null ? this.table[12][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(35, "wdl_entity")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "wdl_entity", + Arrays.asList(this.first.get("wdl_entity")), + this.nonterminal_rules.get("wdl_entity") + )); } - if (rule == 1) { + if (rule == 2) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(1)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen9(); + subtree = this.parse_composite_task(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("wdl_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "wdl_entity", + current, + Arrays.asList(this.first.get("wdl_entity")), + this.rules.get(2) + )); } private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[14][current.getId()] : -1; + int rule = current != null ? this.table[13][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(36, "task_identifier")); tree.setList(null); if (current == null) { @@ -791,12 +785,12 @@ private ParseTree parse_task_identifier() throws SyntaxError { this.nonterminal_rules.get("task_identifier") )); } - if (rule == 42) { + if (rule == 6) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("name", 0); parameters.put("attributes", 1); tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(42)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(6)); tree.add(next); subtree = this.parse__gen4(); tree.add( subtree); @@ -807,127 +801,134 @@ private ParseTree parse_task_identifier() throws SyntaxError { "task_identifier", current, Arrays.asList(this.first.get("task_identifier")), - this.rules.get(42) + this.rules.get(6) )); } - private ParseTree parse_wdl_entity() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "wdl_entity")); + int rule = current != null ? this.table[14][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(37, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "wdl_entity", - Arrays.asList(this.first.get("wdl_entity")), - this.nonterminal_rules.get("wdl_entity") + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") )); } - if (rule == 23) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); + if (rule == 22) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("file", 2); + parameters.put("var", 4); + tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(22)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(22)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(22)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(22)); + tree.add(next); + subtree = this.parse_step_output_location(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("wdl_entity")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl_entity", + "step_output", current, - Arrays.asList(this.first.get("wdl_entity")), - this.rules.get(23) + Arrays.asList(this.first.get("step_output")), + this.rules.get(22) )); } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "composite_task")); + int rule = current != null ? this.table[15][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(38, "step")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task", - Arrays.asList(this.first.get("composite_task")), - this.nonterminal_rules.get("composite_task") + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") )); } - if (rule == 33) { + if (rule == 5) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 3); - parameters.put("name", 1); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(33)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(33)); + parameters.put("task", 1); + parameters.put("name", 2); + parameters.put("body", 4); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(5)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(33)); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(5)); tree.add(next); - subtree = this.parse__gen1(); + subtree = this.parse__gen3(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(33)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(5)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task")); + List terminals = Arrays.asList(this.first.get("step")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task", + "step", current, - Arrays.asList(this.first.get("composite_task")), - this.rules.get(33) + Arrays.asList(this.first.get("step")), + this.rules.get(5) )); } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "step_input")); - tree.setList(null); + int rule = current != null ? this.table[16][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen9")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 18) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") - )); + return tree; } - if (rule == 43) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(43)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(43)); + if (rule == 17) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(17)); tree.add(next); - subtree = this.parse_variable(); + tree.setListSeparator(next); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", - current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(43) - )); + return tree; } private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[18][current.getId()] : -1; + int rule = current != null ? this.table[17][current.getId()] : -1; ParseTree tree = new ParseTree( new NonTerminal(40, "_gen8")); tree.setList("slist"); if ( current != null ) { - if (current.getId() == 15) { + if (current.getId() == 18) { return tree; } } if (current == null) { return tree; } - if (rule == 41) { + if (rule == 13) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_step_output(); tree.add( subtree); @@ -937,330 +938,380 @@ private ParseTree parse__gen8() throws SyntaxError { } return tree; } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "step_attr")); + int rule = current != null ? this.table[18][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(41, "composite_task")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_attr", - Arrays.asList(this.first.get("step_attr")), - this.nonterminal_rules.get("step_attr") + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") )); } - if (rule == 7) { + if (rule == 25) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 1); + parameters.put("body", 3); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(25)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(25)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(25)); + tree.add(next); + subtree = this.parse__gen1(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(25)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task", + current, + Arrays.asList(this.first.get("composite_task")), + this.rules.get(25) + )); + } + private ParseTree parse__gen2() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[19][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(42, "_gen2")); + tree.setList(null); + if ( current != null ) { + if (current.getId() == 21) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 19) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } - else if (rule == 13) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + return tree; + } + private ParseTree parse_step_output_list() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[20][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(43, "step_output_list")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") + )); + } + if (rule == 32) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(32)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(32)); + tree.add(next); + subtree = this.parse__gen8(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(32)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_attr")); + List terminals = Arrays.asList(this.first.get("step_output_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_attr", + "step_output_list", current, - Arrays.asList(this.first.get("step_attr")), - this.rules.get(13) + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(32) )); } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "step_name")); + int rule = current != null ? this.table[21][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(44, "task_attrs")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_name", - Arrays.asList(this.first.get("step_name")), - this.nonterminal_rules.get("step_name") + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") )); } - if (rule == 10) { + if (rule == 45) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(10)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(45)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(10)); + subtree = this.parse__gen5(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(45)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_name")); + List terminals = Arrays.asList(this.first.get("task_attrs")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_name", + "task_attrs", current, - Arrays.asList(this.first.get("step_name")), - this.rules.get(10) + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(45) )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "step_output")); + int rule = current != null ? this.table[22][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(45, "task_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") )); } - if (rule == 6) { + if (rule == 18) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("as", 5); - parameters.put("file", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(6)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(6)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(6)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(6)); + parameters.put("key", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(18)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output", this.rules.get(6)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(18)); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + List terminals = Arrays.asList(this.first.get("task_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "task_attr", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(6) + Arrays.asList(this.first.get("task_attr")), + this.rules.get(18) )); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "_gen2")); + int rule = current != null ? this.table[23][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(46, "composite_task_entity")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 0) { - return tree; - } - } if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task_entity", + Arrays.asList(this.first.get("composite_task_entity")), + this.nonterminal_rules.get("composite_task_entity") + )); + } + if (rule == 9) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); + tree.add( subtree); return tree; } - if (rule == 22) { + else if (rule == 27) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_step(); tree.add( subtree); return tree; } - return tree; + else if (rule == 31) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_for_loop(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task_entity", + current, + Arrays.asList(this.first.get("composite_task_entity")), + this.rules.get(31) + )); } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "step_input_list")); + int rule = current != null ? this.table[24][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(47, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") + "for_loop", + Arrays.asList(this.first.get("for_loop")), + this.nonterminal_rules.get("for_loop") )); } - if (rule == 17) { + if (rule == 43) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(17)); + parameters.put("collection", 4); + parameters.put("item", 2); + parameters.put("body", 7); + tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(43)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(43)); tree.add(next); - subtree = this.parse__gen6(); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(43)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(43)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(43)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(43)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(43)); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(43)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); + List terminals = Arrays.asList(this.first.get("for_loop")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", + "for_loop", current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(17) + Arrays.asList(this.first.get("for_loop")), + this.rules.get(43) )); } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "_gen10")); - tree.setList(null); + int rule = current != null ? this.table[25][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(48, "_gen1")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 19 || current.getId() == 15) { + if (current.getId() == 22) { return tree; } } if (current == null) { return tree; } - if (rule == 39) { + if (rule == 44) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_composite_task_entity(); + tree.add( subtree); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "_gen0")); + int rule = current != null ? this.table[26][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(49, "_gen5")); tree.setList("nlist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 1) { return tree; } } if (current == null) { return tree; } - if (rule == 24) { + if (rule == 42) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + subtree = this.parse_task_attr(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "step")); - tree.setList(null); + int rule = current != null ? this.table[27][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen6")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 18) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step", - Arrays.asList(this.first.get("step")), - this.nonterminal_rules.get("step") - )); + return tree; } - if (rule == 26) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("body", 4); - parameters.put("name", 2); - parameters.put("task", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(26)); - tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen2(); + if (rule == 28) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(26)); - tree.add(next); - subtree = this.parse__gen3(); + subtree = this.parse__gen7(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(26)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step", - current, - Arrays.asList(this.first.get("step")), - this.rules.get(26) - )); + return tree; } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "task_attrs")); + int rule = current != null ? this.table[28][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(51, "_gen4")); tree.setList(null); + if ( current != null ) { + if (current.getId() == 2) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attrs", - Arrays.asList(this.first.get("task_attrs")), - this.nonterminal_rules.get("task_attrs") - )); + return tree; } - if (rule == 4) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(4)); - tree.add(next); - subtree = this.parse__gen5(); + if (rule == 29) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attrs(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(4)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attrs")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attrs", - current, - Arrays.asList(this.first.get("task_attrs")), - this.rules.get(4) - )); + return tree; } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "task_attr_value")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr_value", - Arrays.asList(this.first.get("task_attr_value")), - this.nonterminal_rules.get("task_attr_value") - )); - } - if (rule == 8) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(8)); - tree.add(next); - return tree; + int rule = current != null ? this.table[29][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(52, "_gen0")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == -1) { + return tree; + } } - else if (rule == 12) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(12)); - tree.add(next); + if (current == null) { return tree; } - else if (rule == 16) { + if (rule == 30) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(16)); - tree.add(next); + subtree = this.parse_wdl_entity(); + tree.add( subtree); + subtree = this.parse__gen0(); + tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr_value")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr_value", - current, - Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(16) - )); + return tree; } } From 106c876ac4e8485e5811135a44cbeb300028cd08 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 11 Dec 2012 11:40:03 -0500 Subject: [PATCH 108/140] Making the toString() method for CompositeTaskVariable more useful --- .../java/org/broadinstitute/compositetask/CompositeTaskVariable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java index 38869ea..d5af2e1 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java @@ -47,6 +47,6 @@ public boolean equals(CompositeTaskVariable other) { } public String toString() { - return "[Variable: name=" + this.name + "]"; + return "[Variable: name=" + this.name + (this.member == null ? "" : ", member=" + this.member) + "]"; } } From 14a364b8349aff6217f60bc52ada75ebe0b94c91 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 11 Dec 2012 16:10:26 -0500 Subject: [PATCH 109/140] fixing unit tests --- .../compositetask/CompositeTaskTest.java | 4 +- test-files/parsing/0/ast | 176 ++++--- test-files/parsing/0/parsetree | 40 +- test-files/parsing/1/ast | 200 +++---- test-files/parsing/1/parsetree | 40 +- test-files/parsing/2/.parsetree.swp | Bin 0 -> 16384 bytes test-files/parsing/2/ast | 301 +++++++++++ test-files/parsing/2/parsetree | 584 +++++++++++++++++++++ test-files/parsing/2/source.wdl | 39 ++ test-files/parsing/2/tokens | 197 +++++++ 10 files changed, 1367 insertions(+), 214 deletions(-) create mode 100644 test-files/parsing/2/.parsetree.swp create mode 100644 test-files/parsing/2/ast create mode 100644 test-files/parsing/2/parsetree create mode 100644 test-files/parsing/2/source.wdl create mode 100644 test-files/parsing/2/tokens diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java index cfb0929..16a7c1e 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -24,7 +24,7 @@ { @DataProvider(name="parsingTests") public Object[][] parsingTests() { - File parsingTestDir = new File(System.getProperty("test.files"), "parsing"); + File parsingTestDir = new File("test-files", "parsing"); Collection composite_tasks = new ArrayList(); for ( String subDir : parsingTestDir.list() ) { @@ -51,7 +51,7 @@ public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); File source = new File(dir, "source.wdl"); String actual = null; - + try { SourceCode code = new CompositeTaskSourceCode(source); Lexer lexer = new Lexer(); diff --git a/test-files/parsing/0/ast b/test-files/parsing/0/ast index 4d8e427..2e81e71 100644 --- a/test-files/parsing/0/ast +++ b/test-files/parsing/0/ast @@ -1,55 +1,70 @@ (CompositeTask: + name=identifier, body=[ (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ), (ForLoop: + collection=identifier, + item=identifier, body=[ (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -57,49 +72,51 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], + ] + ), + (Step: task=(Task: + name=identifier, attributes=[ (TaskAttribute: - value=number, - key=identifier + key=identifier, + value=number ) - ], - name=identifier + ] ), - name=None - ), - (Step: + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -107,53 +124,53 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ) - ], - item=identifier, - collection=identifier + ] ), (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -161,26 +178,17 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ) - ], - name=identifier + ] ) \ No newline at end of file diff --git a/test-files/parsing/0/parsetree b/test-files/parsing/0/parsetree index a730f07..553f314 100644 --- a/test-files/parsing/0/parsetree +++ b/test-files/parsing/0/parsetree @@ -41,10 +41,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -144,10 +146,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -238,10 +242,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -338,10 +344,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) diff --git a/test-files/parsing/1/ast b/test-files/parsing/1/ast index 39510d6..ab7c6a9 100644 --- a/test-files/parsing/1/ast +++ b/test-files/parsing/1/ast @@ -1,48 +1,63 @@ (CompositeTask: + name=identifier, body=[ (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ), (ForLoop: + collection=identifier, + item=identifier, body=[ (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -50,42 +65,44 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], + ] + ), + (Step: task=(Task: + name=identifier, attributes=[ (TaskAttribute: - value=number, - key=identifier + key=identifier, + value=number ) - ], - name=identifier + ] ), - name=None - ), - (Step: + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -93,84 +110,84 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ), (ForLoop: + collection=identifier, + item=identifier, body=[ (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ) - ], - item=identifier, - collection=identifier + ] ) - ], - item=identifier, - collection=identifier + ] ), (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, body=[ (StepInputList: inputs=[ (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ), (StepInput: parameter=identifier, value=(Variable: - member=None, - name=identifier + name=identifier, + member=None ) ) ] @@ -178,26 +195,17 @@ (StepOutputList: outputs=[ (StepFileOutput: - as=(Variable: - member=None, - name=identifier - ), - file=string + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) ) ] ) - ], - task=(Task: - attributes=[ - (TaskAttribute: - value=number, - key=identifier - ) - ], - name=identifier - ), - name=None + ] ) - ], - name=identifier + ] ) \ No newline at end of file diff --git a/test-files/parsing/1/parsetree b/test-files/parsing/1/parsetree index 75ce2e2..e27de1f 100644 --- a/test-files/parsing/1/parsetree +++ b/test-files/parsing/1/parsetree @@ -41,10 +41,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -133,10 +135,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -216,10 +220,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) @@ -381,10 +387,12 @@ lparen, string, rparen, - as, - (variable: - identifier, - (_gen10: ) + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) ) ), (_gen9: ) diff --git a/test-files/parsing/2/.parsetree.swp b/test-files/parsing/2/.parsetree.swp new file mode 100644 index 0000000000000000000000000000000000000000..f3efebbf5272f25b907f8fa32bbea36324c963fe GIT binary patch literal 16384 zcmeI2UuYaf9LFd9t4V8%ZP8L6uC@=CCQU9$HEk@lB2q!9w*xe2^l=MiEr-(NrJQ3ciR|upkuFHh$;NX7~1Hb~Y3RaSlGW z*_q$W{N_6|JNuhlrF8EdcNK>Fh6p~Z37MPzZ128KchOrncaUJ*x29~L=45^$v0EL4U*Y1E)UG zKgj;FL*KTO<;~wl0i(d>D6oM2DjKMY6dV1&jhl0i%FXz$jo8FbWt2i~>dhqkvK1 zf2n{qM#u*Ayo<)m`2T+t|NpUykl(;r@Hu!7ybfLjPlAJB4;TV#z=f+|3ueGEa0J-k z7O)XqSV_nka0(m)&jJ_h1v|kOupSWb^9n+~0w=*ya0uKFc7yA{r7l9g2Oohqfd}@1 zUa$mw*Gb67;5c{*)WLqR3v2<`fQwfWat?eAz5u7d3Gf1_fdgPS*bG*K->)F#Tkt7( z7aRr?;7+g!%q>U%!AWowc;Gg$9-LoB$Z7B@2*KT;2dn@;EhXej@IH7AJPrZ z^i^IlpNCYrZpF8%w#pY)b`YbjGEin@Pp9mu<_C{8E#J+RI2GgD~h`u zsM}+0ZBys#*D`M=wo}zbpTBZ<*;0}fE8;oa@B$~a%S<}D<%CbPTe40Jw5O}qn2+BV z+LA{_+=+Haodw#viZ;f*wjHyGw6g1Yjn*FMd*9yg)S^l+cb`3UQWGmxhD{y1wGGME zu*6ukP6NBd_fXbaX@t<^5klktZp63i5EIk*Kl=aqEMofO zUI-6EF=X!6@hj%fJta-`@d80FCMUKnFOB zxcxMk22dhqkuvI8piNYM!YPFyZM+Sj&o8+3-cEAbv?FfzeC7N4;u#BqyCmEXu)(v zJT28QPh`f?%W#~;l1b}*bjRF~o_TN!i91oz*8WAQ{Hi&A;l z-&tLVZ1_NFPfEDCELMpsN?&uGn(#tdXD8gE^^8D!g2D^w&QZ9P?lgs4>CRNRRo2N0 zw@7v*8AbBk_?r!j;*^D3Wt_Ee1NDgu&riCdICn`J%1&QIK0jC_{I2y|xxmzOGjnk% i>!Z!8>(u9pWjWmb$ZG8nT9H43l4jYCaLa#V;r$IL)-^l; literal 0 HcmV?d00001 diff --git a/test-files/parsing/2/ast b/test-files/parsing/2/ast new file mode 100644 index 0000000..2f78fbb --- /dev/null +++ b/test-files/parsing/2/ast @@ -0,0 +1,301 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ), + (CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/2/parsetree b/test-files/parsing/2/parsetree new file mode 100644 index 0000000..b84accc --- /dev/null +++ b/test-files/parsing/2/parsetree @@ -0,0 +1,584 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/2/source.wdl b/test-files/parsing/2/source.wdl new file mode 100644 index 0000000..d85613b --- /dev/null +++ b/test-files/parsing/2/source.wdl @@ -0,0 +1,39 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=item, p1=global; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + + for ( alpha in beta ) { + step dtask[version=0] { + input: p0=y, p1=alpha; + } + + composite_task foo_sub { + step etask[version=0] { + input: p0=global1, p1=y, p2=alpha; + } + step ftask[version=0] { + input: p0=global1, p1=z, p2=alpha; + } + } + } + } + + step gtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/test-files/parsing/2/tokens b/test-files/parsing/2/tokens new file mode 100644 index 0000000..58b8ba8 --- /dev/null +++ b/test-files/parsing/2/tokens @@ -0,0 +1,197 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "composite_task", "line": 23, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 23, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9vX3N1Yg=="}, + {"terminal": "lbrace", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 24, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZXRhc2s="}, + {"terminal": "lsquare", "line": 24, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 24, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 24, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 24, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 24, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 25, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 25, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 25, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 25, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 25, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 25, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 27, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 27, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZnRhc2s="}, + {"terminal": "lsquare", "line": 27, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 27, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 27, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 27, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 27, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 28, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 28, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 28, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 28, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 28, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "comma", "line": 28, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 28, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 28, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 29, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 31, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 32, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 34, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 34, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 34, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 34, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 34, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 34, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 34, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 34, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 35, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 35, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 35, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 35, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 35, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 35, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 35, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 35, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 35, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 36, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 36, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 36, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 36, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 36, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 36, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 36, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 36, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 36, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 37, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 39, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="} +] From c006c3f048cdf2d7282236fb86324ce0f939a1b6 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 10:27:02 -0500 Subject: [PATCH 110/140] Adding ability to test for syntax formatting, and also skipping all tests until they are fixed --- .../compositetask/CompositeTaskTest.java | 34 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java index 16a7c1e..7dc0152 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -46,7 +46,7 @@ private CompositeTask getCompositeTask(File source) { return null; } - @Test(dataProvider="parsingTests") + @Test(dataProvider="parsingTests", enabled=false) public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); File source = new File(dir, "source.wdl"); @@ -81,7 +81,7 @@ public void testLexicalAnalysis(File dir) { } } - @Test(dataProvider="parsingTests") + @Test(dataProvider="parsingTests", enabled=false) public void testParseTree(File dir) { File source = new File(dir, "source.wdl"); File parsetree = new File(dir, "parsetree"); @@ -112,7 +112,7 @@ public void testParseTree(File dir) { } } - @Test(dataProvider="parsingTests") + @Test(dataProvider="parsingTests", enabled=false) public void testAbstractSyntaxTree(File dir) { File source = new File(dir, "source.wdl"); File ast = new File(dir, "ast"); @@ -138,4 +138,32 @@ public void testAbstractSyntaxTree(File dir) { Assert.fail("Cannot read " + ast.getAbsolutePath()); } } + + @Test(dataProvider="parsingTests", enabled=false) + public void testSourceFormatter(File dir) { + File source = new File(dir, "source.wdl"); + File formatted_file = new File(dir, "formatted"); + CompositeTask ctask = getCompositeTask(source); + CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(); + String actual = formatter.format(ctask); + + if ( !formatted_file.exists() ) { + try { + FileWriter out = new FileWriter(formatted_file); + out.write(actual); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write " + formatted_file + ": " + error); + } + + System.out.println("Created " + formatted_file); + } + + try { + String expected = Utility.readFile(formatted_file.getAbsolutePath()); + Assert.assertEquals(actual, expected, "Formatted source code files did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + formatted_file.getAbsolutePath()); + } + } } From e3c4965886732fc7d83aeac5911d8015474ef1ce Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 10:30:34 -0500 Subject: [PATCH 111/140] Adding back tests for only syntax formatting --- .../compositetask/CompositeTaskTest.java | 2 +- test-files/parsing/0/ast | 194 ------- test-files/parsing/0/formatted | 19 + test-files/parsing/0/parsetree | 375 ------------- test-files/parsing/0/tokens | 128 ----- test-files/parsing/1/ast | 211 -------- test-files/parsing/1/formatted | 24 + test-files/parsing/1/parsetree | 418 --------------- test-files/parsing/1/tokens | 143 ----- test-files/parsing/2/.parsetree.swp | Bin 16384 -> 0 bytes test-files/parsing/2/ast | 301 ----------- test-files/parsing/2/formatted | 32 ++ test-files/parsing/2/parsetree | 584 --------------------- test-files/parsing/2/tokens | 197 ------- test-files/parsing/3/formatted | 2 + test-files/parsing/3/source.wdl | 3 + 16 files changed, 81 insertions(+), 2552 deletions(-) delete mode 100644 test-files/parsing/0/ast create mode 100644 test-files/parsing/0/formatted delete mode 100644 test-files/parsing/0/parsetree delete mode 100644 test-files/parsing/0/tokens delete mode 100644 test-files/parsing/1/ast create mode 100644 test-files/parsing/1/formatted delete mode 100644 test-files/parsing/1/parsetree delete mode 100644 test-files/parsing/1/tokens delete mode 100644 test-files/parsing/2/.parsetree.swp delete mode 100644 test-files/parsing/2/ast create mode 100644 test-files/parsing/2/formatted delete mode 100644 test-files/parsing/2/parsetree delete mode 100644 test-files/parsing/2/tokens create mode 100644 test-files/parsing/3/formatted create mode 100644 test-files/parsing/3/source.wdl diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java index 7dc0152..0f73e00 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java @@ -139,7 +139,7 @@ public void testAbstractSyntaxTree(File dir) { } } - @Test(dataProvider="parsingTests", enabled=false) + @Test(dataProvider="parsingTests") public void testSourceFormatter(File dir) { File source = new File(dir, "source.wdl"); File formatted_file = new File(dir, "formatted"); diff --git a/test-files/parsing/0/ast b/test-files/parsing/0/ast deleted file mode 100644 index 2e81e71..0000000 --- a/test-files/parsing/0/ast +++ /dev/null @@ -1,194 +0,0 @@ -(CompositeTask: - name=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (ForLoop: - collection=identifier, - item=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ) - ] -) \ No newline at end of file diff --git a/test-files/parsing/0/formatted b/test-files/parsing/0/formatted new file mode 100644 index 0000000..ec388cd --- /dev/null +++ b/test-files/parsing/0/formatted @@ -0,0 +1,19 @@ +composite_task foo { + step atask[version=0] { + output: File("foo.txt") as x; + } + for ( item in foo ) { + step ctask[version=0] { + input: p0=x, p1=item, p2=y; + output: File("quux.txt") as z; + } + step btask[version=0] { + input: p0=x, p1=item, p2=GLOBAL; + output: File("bar.txt") as y; + } + } + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } +} diff --git a/test-files/parsing/0/parsetree b/test-files/parsing/0/parsetree deleted file mode 100644 index 553f314..0000000 --- a/test-files/parsing/0/parsetree +++ /dev/null @@ -1,375 +0,0 @@ -(wdl: - (_gen0: - (wdl_entity: - (composite_task: - composite_task, - identifier, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (for_loop: - for, - lparen, - identifier, - in, - identifier, - rparen, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ) - ), - rbrace - ) - ), - (_gen0: ) - ) -) \ No newline at end of file diff --git a/test-files/parsing/0/tokens b/test-files/parsing/0/tokens deleted file mode 100644 index 308d6b4..0000000 --- a/test-files/parsing/0/tokens +++ /dev/null @@ -1,128 +0,0 @@ -[ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "R0xPQkFM"}, - {"terminal": "semi", "line": 9, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 20, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 21, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 21, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 21, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 21, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 21, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 24, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="} -] diff --git a/test-files/parsing/1/ast b/test-files/parsing/1/ast deleted file mode 100644 index ab7c6a9..0000000 --- a/test-files/parsing/1/ast +++ /dev/null @@ -1,211 +0,0 @@ -(CompositeTask: - name=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (ForLoop: - collection=identifier, - item=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (ForLoop: - collection=identifier, - item=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ) - ] - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ) - ] -) \ No newline at end of file diff --git a/test-files/parsing/1/formatted b/test-files/parsing/1/formatted new file mode 100644 index 0000000..6eb690b --- /dev/null +++ b/test-files/parsing/1/formatted @@ -0,0 +1,24 @@ +composite_task foo { + step atask[version=0] { + output: File("foo.txt") as x; + } + for ( item in foo ) { + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + step btask[version=0] { + input: p0=item, p1=global; + output: File("bar.txt") as y; + } + for ( alpha in beta ) { + step dtask[version=0] { + input: p0=alpha; + } + } + } + step gtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } +} diff --git a/test-files/parsing/1/parsetree b/test-files/parsing/1/parsetree deleted file mode 100644 index e27de1f..0000000 --- a/test-files/parsing/1/parsetree +++ /dev/null @@ -1,418 +0,0 @@ -(wdl: - (_gen0: - (wdl_entity: - (composite_task: - composite_task, - identifier, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (for_loop: - for, - lparen, - identifier, - in, - identifier, - rparen, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (for_loop: - for, - lparen, - identifier, - in, - identifier, - rparen, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ) - ), - rbrace - ) - ), - (_gen0: ) - ) -) \ No newline at end of file diff --git a/test-files/parsing/1/tokens b/test-files/parsing/1/tokens deleted file mode 100644 index 49b2aec..0000000 --- a/test-files/parsing/1/tokens +++ /dev/null @@ -1,143 +0,0 @@ -[ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z2xvYmFs"}, - {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z3Rhc2s="}, - {"terminal": "lsquare", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 25, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 25, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 25, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 26, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 26, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 26, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 26, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 27, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="} -] diff --git a/test-files/parsing/2/.parsetree.swp b/test-files/parsing/2/.parsetree.swp deleted file mode 100644 index f3efebbf5272f25b907f8fa32bbea36324c963fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI2UuYaf9LFd9t4V8%ZP8L6uC@=CCQU9$HEk@lB2q!9w*xe2^l=MiEr-(NrJQ3ciR|upkuFHh$;NX7~1Hb~Y3RaSlGW z*_q$W{N_6|JNuhlrF8EdcNK>Fh6p~Z37MPzZ128KchOrncaUJ*x29~L=45^$v0EL4U*Y1E)UG zKgj;FL*KTO<;~wl0i(d>D6oM2DjKMY6dV1&jhl0i%FXz$jo8FbWt2i~>dhqkvK1 zf2n{qM#u*Ayo<)m`2T+t|NpUykl(;r@Hu!7ybfLjPlAJB4;TV#z=f+|3ueGEa0J-k z7O)XqSV_nka0(m)&jJ_h1v|kOupSWb^9n+~0w=*ya0uKFc7yA{r7l9g2Oohqfd}@1 zUa$mw*Gb67;5c{*)WLqR3v2<`fQwfWat?eAz5u7d3Gf1_fdgPS*bG*K->)F#Tkt7( z7aRr?;7+g!%q>U%!AWowc;Gg$9-LoB$Z7B@2*KT;2dn@;EhXej@IH7AJPrZ z^i^IlpNCYrZpF8%w#pY)b`YbjGEin@Pp9mu<_C{8E#J+RI2GgD~h`u zsM}+0ZBys#*D`M=wo}zbpTBZ<*;0}fE8;oa@B$~a%S<}D<%CbPTe40Jw5O}qn2+BV z+LA{_+=+Haodw#viZ;f*wjHyGw6g1Yjn*FMd*9yg)S^l+cb`3UQWGmxhD{y1wGGME zu*6ukP6NBd_fXbaX@t<^5klktZp63i5EIk*Kl=aqEMofO zUI-6EF=X!6@hj%fJta-`@d80FCMUKnFOB zxcxMk22dhqkuvI8piNYM!YPFyZM+Sj&o8+3-cEAbv?FfzeC7N4;u#BqyCmEXu)(v zJT28QPh`f?%W#~;l1b}*bjRF~o_TN!i91oz*8WAQ{Hi&A;l z-&tLVZ1_NFPfEDCELMpsN?&uGn(#tdXD8gE^^8D!g2D^w&QZ9P?lgs4>CRNRRo2N0 zw@7v*8AbBk_?r!j;*^D3Wt_Ee1NDgu&riCdICn`J%1&QIK0jC_{I2y|xxmzOGjnk% i>!Z!8>(u9pWjWmb$ZG8nT9H43l4jYCaLa#V;r$IL)-^l; diff --git a/test-files/parsing/2/ast b/test-files/parsing/2/ast deleted file mode 100644 index 2f78fbb..0000000 --- a/test-files/parsing/2/ast +++ /dev/null @@ -1,301 +0,0 @@ -(CompositeTask: - name=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (ForLoop: - collection=identifier, - item=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ), - (ForLoop: - collection=identifier, - item=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ) - ] - ), - (CompositeTask: - name=identifier, - body=[ - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ) - ] - ) - ] - ) - ] - ) - ] - ), - (Step: - task=(Task: - name=identifier, - attributes=[ - (TaskAttribute: - key=identifier, - value=number - ) - ] - ), - name=None, - body=[ - (StepInputList: - inputs=[ - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ), - (StepInput: - parameter=identifier, - value=(Variable: - name=identifier, - member=None - ) - ) - ] - ), - (StepOutputList: - outputs=[ - (StepFileOutput: - file=string, - var=(OutputVariable: - var=(Variable: - name=identifier, - member=None - ) - ) - ) - ] - ) - ] - ) - ] -) \ No newline at end of file diff --git a/test-files/parsing/2/formatted b/test-files/parsing/2/formatted new file mode 100644 index 0000000..cc38fec --- /dev/null +++ b/test-files/parsing/2/formatted @@ -0,0 +1,32 @@ +composite_task foo { + step atask[version=0] { + output: File("foo.txt") as x; + } + for ( item in foo ) { + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + step btask[version=0] { + input: p0=item, p1=global; + output: File("bar.txt") as y; + } + for ( alpha in beta ) { + step dtask[version=0] { + input: p0=y, p1=alpha; + } + composite_task foo_sub { + step etask[version=0] { + input: p0=global1, p1=y, p2=alpha; + } + step ftask[version=0] { + input: p0=global1, p1=z, p2=alpha; + } + } + } + } + step gtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } +} diff --git a/test-files/parsing/2/parsetree b/test-files/parsing/2/parsetree deleted file mode 100644 index b84accc..0000000 --- a/test-files/parsing/2/parsetree +++ /dev/null @@ -1,584 +0,0 @@ -(wdl: - (_gen0: - (wdl_entity: - (composite_task: - composite_task, - identifier, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (for_loop: - for, - lparen, - identifier, - in, - identifier, - rparen, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (for_loop: - for, - lparen, - identifier, - in, - identifier, - rparen, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (composite_task: - composite_task, - identifier, - lbrace, - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ) - ), - rbrace - ) - ), - (_gen1: - (composite_task_entity: - (step: - step, - (task_identifier: - identifier, - (_gen4: - (task_attrs: - lsquare, - (_gen5: - (task_attr: - identifier, - assign, - (task_attr_value: - number - ) - ), - (_gen5: ) - ), - rsquare - ) - ) - ), - (_gen2: ), - lbrace, - (_gen3: - (step_attr: - (step_input_list: - input, - colon, - (_gen6: - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: - comma, - (step_input: - identifier, - assign, - (variable: - identifier, - (_gen10: ) - ) - ), - (_gen7: ) - ) - ) - ), - semi - ) - ), - (_gen3: - (step_attr: - (step_output_list: - output, - colon, - (_gen8: - (step_output: - file, - lparen, - string, - rparen, - (step_output_location: - as, - (variable: - identifier, - (_gen10: ) - ) - ) - ), - (_gen9: ) - ), - semi - ) - ), - (_gen3: ) - ) - ), - rbrace - ) - ), - (_gen1: ) - ) - ) - ), - rbrace - ) - ), - (_gen0: ) - ) -) \ No newline at end of file diff --git a/test-files/parsing/2/tokens b/test-files/parsing/2/tokens deleted file mode 100644 index 58b8ba8..0000000 --- a/test-files/parsing/2/tokens +++ /dev/null @@ -1,197 +0,0 @@ -[ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFs"}, - {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "composite_task", "line": 23, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 23, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9vX3N1Yg=="}, - {"terminal": "lbrace", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 24, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZXRhc2s="}, - {"terminal": "lsquare", "line": 24, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 24, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 24, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 24, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 24, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 25, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 25, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, - {"terminal": "comma", "line": 25, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 25, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 25, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 25, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 25, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 27, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 27, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZnRhc2s="}, - {"terminal": "lsquare", "line": 27, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 27, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 27, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 27, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 27, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 28, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 28, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 28, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, - {"terminal": "comma", "line": 28, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 28, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "comma", "line": 28, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 28, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 28, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 28, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 29, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 30, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 31, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 32, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 34, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 34, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z3Rhc2s="}, - {"terminal": "lsquare", "line": 34, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 34, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 34, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 34, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 34, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 34, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 35, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 35, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 35, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 35, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 35, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 35, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 35, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 35, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 35, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 35, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 35, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 36, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 36, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 36, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 36, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 36, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 36, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 36, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 36, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 36, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 37, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 39, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="} -] diff --git a/test-files/parsing/3/formatted b/test-files/parsing/3/formatted new file mode 100644 index 0000000..6e746d5 --- /dev/null +++ b/test-files/parsing/3/formatted @@ -0,0 +1,2 @@ +composite_task foo { +} diff --git a/test-files/parsing/3/source.wdl b/test-files/parsing/3/source.wdl new file mode 100644 index 0000000..5159ed5 --- /dev/null +++ b/test-files/parsing/3/source.wdl @@ -0,0 +1,3 @@ +composite_task foo { + +} From c035becdcd9ddeebecbef6e2dfef66341acb94ec Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 11:29:15 -0500 Subject: [PATCH 112/140] removing old example files --- examples/0.wdl | 24 ------------------------ examples/1.wdl | 39 --------------------------------------- examples/2.wdl | 30 ------------------------------ examples/3.wdl | 28 ---------------------------- examples/4.wdl | 30 ------------------------------ examples/5.wdl | 33 --------------------------------- examples/6.wdl | 12 ------------ examples/7.wdl | 18 ------------------ examples/8.wdl | 1 - examples/error0.wdl | 24 ------------------------ examples/error1.wdl | 12 ------------ examples/error2.wdl | 12 ------------ examples/error3.wdl | 12 ------------ examples/unformatted.wdl | 8 -------- 14 files changed, 283 deletions(-) delete mode 100644 examples/0.wdl delete mode 100644 examples/1.wdl delete mode 100644 examples/2.wdl delete mode 100644 examples/3.wdl delete mode 100644 examples/4.wdl delete mode 100644 examples/5.wdl delete mode 100644 examples/6.wdl delete mode 100644 examples/7.wdl delete mode 100644 examples/8.wdl delete mode 100644 examples/error0.wdl delete mode 100644 examples/error1.wdl delete mode 100644 examples/error2.wdl delete mode 100644 examples/error3.wdl delete mode 100644 examples/unformatted.wdl diff --git a/examples/0.wdl b/examples/0.wdl deleted file mode 100644 index c994a2a..0000000 --- a/examples/0.wdl +++ /dev/null @@ -1,24 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; - } - - for ( item in foo ) { - step btask[version=0] { - input: p0=x, p1=item, p2=GLOBAL; - output: File("bar.txt") as y; - } - - step ctask[version=0] { - input: p0=x, p1=item, p2=y; - output: File("quux.txt") as z; - } - } - - step dtask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as r; - } - -} diff --git a/examples/1.wdl b/examples/1.wdl deleted file mode 100644 index 99e75d5..0000000 --- a/examples/1.wdl +++ /dev/null @@ -1,39 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; - } - - for ( item in foo ) { - step btask[version=0] { - input: p0=x, p1=global; - output: File("bar.txt") as y; - } - - step ctask[version=0] { - input: p0=x, p1=y; - output: File("quux.txt") as z; - } - - for ( alpha in beta ) { - step dtask[version=0] { - input: p0=y; - } - - composite_task foo_sub { - step etask[version=0] { - input: p0=global1, p1=y; - } - step ftask[version=0] { - input: p0=global1, p1=z; - } - } - } - } - - step gtask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as r; - } - -} diff --git a/examples/2.wdl b/examples/2.wdl deleted file mode 100644 index 0f6c450..0000000 --- a/examples/2.wdl +++ /dev/null @@ -1,30 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; - } - - for ( item in foo ) { - step btask[version=0] { - input: p0=x, p1=global; - output: File("bar.txt") as list; - } - } - - for ( item in list ) { - step ctask[version=0] { - input: p0=x, p1=item, p2=list, p3=blah; - output: File("quux.txt") as z; - } - } - - step dtask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as r; - } - - step etask[version=0] { - output: File("blah.txt") as blah; - } - -} diff --git a/examples/3.wdl b/examples/3.wdl deleted file mode 100644 index 97ea303..0000000 --- a/examples/3.wdl +++ /dev/null @@ -1,28 +0,0 @@ -composite_task foo { - - step short_task[version=0] { - output: File("foo.txt") as alpha; - } - - step long_task[version=0] { - output: File("bar.txt") as beta; - } - - for ( item in items ) { - step atask[version=0] { - input: p0=alpha; - output: File("baz.txt") as gamma; - } - - step btask[version=0] { - input: p0=beta; - output: File("quux.txt") as epsilon; - } - } - - step generate_report[version=0] { - input: p0=gamma, p1=epsilon; - output: File("report.txt") as report; - } - -} diff --git a/examples/4.wdl b/examples/4.wdl deleted file mode 100644 index cad77ce..0000000 --- a/examples/4.wdl +++ /dev/null @@ -1,30 +0,0 @@ -composite_task foo { - - step short_task[version=0] { - output: File("foo.txt") as alpha; - } - - step long_task[version=0] { - output: File("bar.txt") as beta; - } - - for ( item in items ) { - step atask[version=0] { - input: p0=alpha; - output: File("baz.txt") as gamma; - } - } - - for ( item in items ) { - step btask[version=0] { - input: p0=beta; - output: File("quux.txt") as epsilon; - } - } - - step generate_report[version=0] { - input: p0=gamma, p1=epsilon; - output: File("report.txt") as report; - } - -} diff --git a/examples/5.wdl b/examples/5.wdl deleted file mode 100644 index f1d7118..0000000 --- a/examples/5.wdl +++ /dev/null @@ -1,33 +0,0 @@ -composite_task foo { - - for ( item in items ) { - step atask[version=0] { - input: p0=alpha; - output: File("baz.txt") as gamma; - } - } - - step short_task[version=0] { - output: File("foo.txt") as alpha; - } - - step long_task[version=0] { - output: File("bar.txt") as beta; - } - - step batman[version=0] {} - step robin[version=0] {} - - step generate_report[version=0] { - input: p0=gamma, p1=epsilon; - output: File("report.txt") as report; - } - - for ( item in items ) { - step btask[version=0] { - input: p0=beta; - output: File("quux.txt") as epsilon; - } - } - -} diff --git a/examples/6.wdl b/examples/6.wdl deleted file mode 100644 index c4371f6..0000000 --- a/examples/6.wdl +++ /dev/null @@ -1,12 +0,0 @@ -composite_task test { - for (item in collection) { - step task[version=0] { - input: p0=x, p1=y, p2=item.z; - output: File("xyz") as list; - } - } - - step task1[version=0] { - input: p0=list; - } -} diff --git a/examples/7.wdl b/examples/7.wdl deleted file mode 100644 index 9cfe189..0000000 --- a/examples/7.wdl +++ /dev/null @@ -1,18 +0,0 @@ -composite_task test { - step s0[version=0] { - output: File("abc") as foo; - } - - for (I in L) { - for (J in M) { - step s1[version=0] { - input: p0=I, p1=J, p2=foo; - output: File("def") as bar; - } - } - } - - step s2[version=0] { - input: p0=bar; - } -} diff --git a/examples/8.wdl b/examples/8.wdl deleted file mode 100644 index 195e03f..0000000 --- a/examples/8.wdl +++ /dev/null @@ -1 +0,0 @@ -composite_task x {step y[version=0] {}} diff --git a/examples/error0.wdl b/examples/error0.wdl deleted file mode 100644 index 6ac7df5..0000000 --- a/examples/error0.wdl +++ /dev/null @@ -1,24 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; - } - - for ( item in foo ) { - step btask[version=0] { - input: p0=x, p1=GLOBAL; - output: File("bar.txt") as y; - } - - step ctask[version=0] { - input: p0=x, p1=y; - output: File("quux.txt") as z; - } - } - - step dtask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as r; - } - -} diff --git a/examples/error1.wdl b/examples/error1.wdl deleted file mode 100644 index e270d49..0000000 --- a/examples/error1.wdl +++ /dev/null @@ -1,12 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as x; - } - - step btask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("report.txt") as x; - } - -} diff --git a/examples/error2.wdl b/examples/error2.wdl deleted file mode 100644 index 5213c5b..0000000 --- a/examples/error2.wdl +++ /dev/null @@ -1,12 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as abc; - } - - step btask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("foo.txt") as xyz; - } - -} diff --git a/examples/error3.wdl b/examples/error3.wdl deleted file mode 100644 index 5674ce3..0000000 --- a/examples/error3.wdl +++ /dev/null @@ -1,12 +0,0 @@ -composite_task foo { - - step atask[version=0] { - output: File("foo.txt") as abc; - } - - step atask[version=0] { - input: p0=x, p1=y, p2=z; - output: File("bar.txt") as xyz; - } - -} diff --git a/examples/unformatted.wdl b/examples/unformatted.wdl deleted file mode 100644 index 0989568..0000000 --- a/examples/unformatted.wdl +++ /dev/null @@ -1,8 +0,0 @@ -composite_task foo { - step atask[version=0] {output: File("foo.txt") as x;} - for ( item in foo ) { - step btask[version=0] {input: p0=x, p1=item, p2=GLOBAL; output: File("bar.txt") as y;} - step ctask[version=0] {input: p0=x, p1=item, p2=y; output: File("quux.txt") as z;} - } - step dtask[version=0] {input: p0=x, p1=y, p2=z; output: File("report.txt") as r;} -} From b5117e06f8fb8914a03a5a27b16a54ed332c9f4a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 11:29:31 -0500 Subject: [PATCH 113/140] Updating the copy number QC example --- examples/CopyNumberQC.wdl | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/examples/CopyNumberQC.wdl b/examples/CopyNumberQC.wdl index 8f4790d..7200425 100644 --- a/examples/CopyNumberQC.wdl +++ b/examples/CopyNumberQC.wdl @@ -2,20 +2,17 @@ composite_task CopyNumberQC { step LaneBlackList[version=6] { output: File("lane_blacklist.txt") as lane_blacklist; } - for ( sample in samples ) { - step MakeLaneList[version=11] as foobar { - input: bam=sample.bam, id=sample.id, regions=sample.regions; - output: File("${sample.id}.lanelist") as lanelist; - } - step RegionCovPerLane[version=16] { - input: bam=sample.bam, id=sample.id, regions=sample.regions; - output: File("${sample.id}.rcl") as rcl; + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.rcl") into rcl; + } + step MakeLaneList[version=11] { + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.lanelist") into lanelist; } } - step CopyNumberQC[version=25] { - input: lanelist=lanelist, rcl=rcl, lane_blacklist=lane_blacklist; + input: lanes_list=lanelist, rcl_list=rcl, lane_blacklist=lane_blacklist; } } From d9f6ffc06b7220a67a582c5660c96d63de2f70f0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 11:30:49 -0500 Subject: [PATCH 114/140] Unit tests, hooray --- .../compositetask/CompositeTask.java | 2 +- .../CompositeTaskSourceCodeFormatter.java | 4 +- .../compositetask/.ParsingTest.java.swp | Bin 0 -> 16384 bytes .../compositetask/.SyntaxErrorTest.java.swp | Bin 0 -> 12288 bytes .../{CompositeTaskTest.java => ParsingTest.java} | 55 +- .../compositetask/SyntaxErrorTest.java | 73 +++ test-files/parsing/0/ast | 194 +++++++ test-files/parsing/0/formatted | 8 +- test-files/parsing/0/parsetree | 375 +++++++++++++ test-files/parsing/0/tokens | 128 +++++ test-files/parsing/1/ast | 211 ++++++++ test-files/parsing/1/formatted | 10 +- test-files/parsing/1/parsetree | 418 +++++++++++++++ test-files/parsing/1/tokens | 143 +++++ test-files/parsing/10/ast | 14 + test-files/parsing/10/formatted | 6 + test-files/parsing/10/parsetree | 36 ++ test-files/parsing/10/source.wdl | 1 + test-files/parsing/10/tokens | 14 + test-files/parsing/11/ast | 194 +++++++ test-files/parsing/11/formatted | 19 + test-files/parsing/11/parsetree | 375 +++++++++++++ test-files/parsing/11/source.wdl | 8 + test-files/parsing/11/tokens | 128 +++++ test-files/parsing/2/ast | 301 +++++++++++ test-files/parsing/2/formatted | 12 +- test-files/parsing/2/parsetree | 584 +++++++++++++++++++++ test-files/parsing/2/tokens | 197 +++++++ test-files/parsing/3/ast | 4 + test-files/parsing/3/parsetree | 14 + test-files/parsing/3/source.wdl | 4 +- test-files/parsing/3/tokens | 6 + test-files/parsing/4/ast | 200 +++++++ test-files/parsing/4/formatted | 22 + test-files/parsing/4/parsetree | 407 ++++++++++++++ test-files/parsing/4/source.wdl | 28 + test-files/parsing/4/tokens | 138 +++++ test-files/parsing/5/ast | 206 ++++++++ test-files/parsing/5/formatted | 24 + test-files/parsing/5/parsetree | 422 +++++++++++++++ test-files/parsing/5/source.wdl | 30 ++ test-files/parsing/5/tokens | 146 ++++++ test-files/parsing/6/ast | 232 ++++++++ test-files/parsing/6/formatted | 28 + test-files/parsing/6/parsetree | 472 +++++++++++++++++ test-files/parsing/6/source.wdl | 33 ++ test-files/parsing/6/tokens | 160 ++++++ test-files/parsing/7/ast | 88 ++++ test-files/parsing/7/formatted | 11 + test-files/parsing/7/parsetree | 181 +++++++ test-files/parsing/7/source.wdl | 12 + test-files/parsing/7/tokens | 63 +++ test-files/parsing/8/ast | 121 +++++ test-files/parsing/8/formatted | 16 + test-files/parsing/8/parsetree | 246 +++++++++ test-files/parsing/8/source.wdl | 18 + test-files/parsing/8/tokens | 87 +++ test-files/parsing/9/ast | 18 + test-files/parsing/9/formatted | 4 + test-files/parsing/9/parsetree | 44 ++ test-files/parsing/9/source.wdl | 1 + test-files/parsing/9/tokens | 15 + test-files/syntax-error/0/source.wdl | 24 + test-files/syntax-error/1/source.wdl | 12 + test-files/syntax-error/2/source.wdl | 12 + test-files/syntax-error/3/source.wdl | 12 + 66 files changed, 7042 insertions(+), 29 deletions(-) create mode 100644 src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp create mode 100644 src/test/java/org/broadinstitute/compositetask/.SyntaxErrorTest.java.swp rename src/test/java/org/broadinstitute/compositetask/{CompositeTaskTest.java => ParsingTest.java} (75%) create mode 100644 src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java create mode 100644 test-files/parsing/0/ast create mode 100644 test-files/parsing/0/parsetree create mode 100644 test-files/parsing/0/tokens create mode 100644 test-files/parsing/1/ast create mode 100644 test-files/parsing/1/parsetree create mode 100644 test-files/parsing/1/tokens create mode 100644 test-files/parsing/10/ast create mode 100644 test-files/parsing/10/formatted create mode 100644 test-files/parsing/10/parsetree create mode 100644 test-files/parsing/10/source.wdl create mode 100644 test-files/parsing/10/tokens create mode 100644 test-files/parsing/11/ast create mode 100644 test-files/parsing/11/formatted create mode 100644 test-files/parsing/11/parsetree create mode 100644 test-files/parsing/11/source.wdl create mode 100644 test-files/parsing/11/tokens create mode 100644 test-files/parsing/2/ast create mode 100644 test-files/parsing/2/parsetree create mode 100644 test-files/parsing/2/tokens create mode 100644 test-files/parsing/3/ast create mode 100644 test-files/parsing/3/parsetree create mode 100644 test-files/parsing/3/tokens create mode 100644 test-files/parsing/4/ast create mode 100644 test-files/parsing/4/formatted create mode 100644 test-files/parsing/4/parsetree create mode 100644 test-files/parsing/4/source.wdl create mode 100644 test-files/parsing/4/tokens create mode 100644 test-files/parsing/5/ast create mode 100644 test-files/parsing/5/formatted create mode 100644 test-files/parsing/5/parsetree create mode 100644 test-files/parsing/5/source.wdl create mode 100644 test-files/parsing/5/tokens create mode 100644 test-files/parsing/6/ast create mode 100644 test-files/parsing/6/formatted create mode 100644 test-files/parsing/6/parsetree create mode 100644 test-files/parsing/6/source.wdl create mode 100644 test-files/parsing/6/tokens create mode 100644 test-files/parsing/7/ast create mode 100644 test-files/parsing/7/formatted create mode 100644 test-files/parsing/7/parsetree create mode 100644 test-files/parsing/7/source.wdl create mode 100644 test-files/parsing/7/tokens create mode 100644 test-files/parsing/8/ast create mode 100644 test-files/parsing/8/formatted create mode 100644 test-files/parsing/8/parsetree create mode 100644 test-files/parsing/8/source.wdl create mode 100644 test-files/parsing/8/tokens create mode 100644 test-files/parsing/9/ast create mode 100644 test-files/parsing/9/formatted create mode 100644 test-files/parsing/9/parsetree create mode 100644 test-files/parsing/9/source.wdl create mode 100644 test-files/parsing/9/tokens create mode 100644 test-files/syntax-error/0/source.wdl create mode 100644 test-files/syntax-error/1/source.wdl create mode 100644 test-files/syntax-error/2/source.wdl create mode 100644 test-files/syntax-error/3/source.wdl diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index f9757c6..8b4bd55 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -198,7 +198,7 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { } private CompositeTaskForLoop verify_for(Ast for_node_ast) throws SyntaxError { - Set nodes = new HashSet(); + Set nodes = new LinkedHashSet(); String collection = ((Terminal) for_node_ast.getAttribute("collection")).getSourceString(); String item = ((Terminal) for_node_ast.getAttribute("item")).getSourceString(); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java index 46174b4..8afcd48 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java @@ -27,7 +27,6 @@ private String format(CompositeTaskNode node, int indent) { CompositeTask ctask = (CompositeTask) node; builder.append(indent_str + this.colorizer.keyword("composite_task") + " " + ctask.getName() + " {\n"); for ( CompositeTaskNode sub_node : ctask.getNodes() ) { - builder.append( indent_str ); builder.append( format(sub_node, indent + 2) ); } builder.append(indent_str + "}\n"); @@ -35,7 +34,6 @@ private String format(CompositeTaskNode node, int indent) { CompositeTaskForLoop loop = (CompositeTaskForLoop) node; builder.append( indent_str + this.colorizer.keyword("for") + " ( " + this.colorizer.variable(variable_to_string(loop.getVariable())) + " " + this.colorizer.keyword("in") + " " + this.colorizer.variable(variable_to_string(loop.getCollection())) + " ) {\n" ); for ( CompositeTaskNode sub_node : loop.getNodes() ) { - builder.append( indent_str ); builder.append( format(sub_node, indent + 2) ); } builder.append( indent_str + "}\n" ); @@ -46,7 +44,7 @@ private String format(CompositeTaskNode node, int indent) { if ( !step.getName().equals(task.getTaskName()) ) { rename = " " + this.colorizer.keyword("as") + " " + step.getName(); } - builder.append( " " + this.colorizer.keyword("step") + " " + this.colorizer.task(task.getTaskName()) + "[version=" + task.getVersion() + "]" + rename + " {\n" ); + builder.append( indent_str + this.colorizer.keyword("step") + " " + this.colorizer.task(task.getTaskName()) + "[version=" + task.getVersion() + "]" + rename + " {\n" ); if ( step.getInputs().size() > 0 ) { List parameters = new ArrayList(); diff --git a/src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp b/src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..b8c4ade131d0203fcef6551786f6edf9eca9af1e GIT binary patch literal 16384 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 Vl;h^=0AQ;wo?ooZj}5^z`47F?L(l*K literal 0 HcmV?d00001 diff --git a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java similarity index 75% rename from src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java rename to src/test/java/org/broadinstitute/compositetask/ParsingTest.java index 0f73e00..45cff01 100644 --- a/src/test/java/org/broadinstitute/compositetask/CompositeTaskTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java @@ -20,7 +20,7 @@ import org.broadinstitute.compositetask.CompositeTaskSourceCode; import org.broadinstitute.compositetask.Lexer; -public class CompositeTaskTest +public class ParsingTest { @DataProvider(name="parsingTests") public Object[][] parsingTests() { @@ -46,7 +46,7 @@ private CompositeTask getCompositeTask(File source) { return null; } - @Test(dataProvider="parsingTests", enabled=false) + @Test(dataProvider="parsingTests") public void testLexicalAnalysis(File dir) { File tokens = new File(dir, "tokens"); File source = new File(dir, "source.wdl"); @@ -81,8 +81,8 @@ public void testLexicalAnalysis(File dir) { } } - @Test(dataProvider="parsingTests", enabled=false) - public void testParseTree(File dir) { + @Test(dataProvider="parsingTests") + public void testParseTreeIsGeneratedFromSourceCodeCorrectly(File dir) { File source = new File(dir, "source.wdl"); File parsetree = new File(dir, "parsetree"); CompositeTask ctask = getCompositeTask(source); @@ -112,8 +112,8 @@ public void testParseTree(File dir) { } } - @Test(dataProvider="parsingTests", enabled=false) - public void testAbstractSyntaxTree(File dir) { + @Test(dataProvider="parsingTests") + public void testAbstractSyntaxTreeIsGeneratedFromSourceCodeCorrectly(File dir) { File source = new File(dir, "source.wdl"); File ast = new File(dir, "ast"); CompositeTask ctask = getCompositeTask(source); @@ -140,7 +140,7 @@ public void testAbstractSyntaxTree(File dir) { } @Test(dataProvider="parsingTests") - public void testSourceFormatter(File dir) { + public void testSourceFormatterOutputsCorrectlyFormattedSourceCode(File dir) { File source = new File(dir, "source.wdl"); File formatted_file = new File(dir, "formatted"); CompositeTask ctask = getCompositeTask(source); @@ -166,4 +166,45 @@ public void testSourceFormatter(File dir) { Assert.fail("Cannot read " + formatted_file.getAbsolutePath()); } } + + @Test(dataProvider="parsingTests", enabled=false) + public void testCompositeTaskGeneratesCorrectGraph(File dir) { + File source = new File(dir, "source.wdl"); + File graph_file = new File(dir, "graph"); + CompositeTask ctask = getCompositeTask(source); + CompositeTaskGraph graph = ctask.getGraph(); + + StringBuilder actual = new StringBuilder(); + actual.append("VERTICIES\n"); + actual.append("---------\n"); + for ( CompositeTaskVertex v : graph.vertexSet() ) { + actual.append(v + "\n"); + } + actual.append("\n"); + + actual.append("EDGES\n"); + actual.append("-----\n"); + for ( CompositeTaskEdge v : graph.edgeSet() ) { + actual.append(v + "\n"); + } + + if ( !graph_file.exists() ) { + try { + FileWriter out = new FileWriter(graph_file); + out.write(actual.toString()); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write " + graph_file + ": " + error); + } + + System.out.println("Created " + graph_file); + } + + try { + String expected = Utility.readFile(graph_file.getAbsolutePath()); + Assert.assertEquals(actual.toString(), expected, "Graphs did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + graph_file.getAbsolutePath()); + } + } } diff --git a/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java new file mode 100644 index 0000000..b3ec894 --- /dev/null +++ b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java @@ -0,0 +1,73 @@ +package org.broadinstitute.compositetask; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import org.testng.Assert; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.ArrayList; + +import org.broadinstitute.parser.SyntaxError; +import org.broadinstitute.parser.Utility; + +import org.broadinstitute.compositetask.CompositeTask; + +public class SyntaxErrorTest +{ + @DataProvider(name="syntaxErrorTests") + public Object[][] parsingTests() { + File parsingTestDir = new File("test-files", "syntax-errors"); + Collection composite_tasks = new ArrayList(); + + for ( String subDir : parsingTestDir.list() ) { + composite_tasks.add(new Object[] { new File(parsingTestDir, subDir) }); + } + + return composite_tasks.toArray(new Object[0][]); + } + + private CompositeTask getCompositeTask(File source) throws SyntaxError { + try { + return new CompositeTask(source); + } catch(IOException error) { + Assert.fail("IOException reading file: " + error); + } + + return null; + } + + @Test(dataProvider="syntaxErrorTests") + public void testCompositeTaskReportsBackCorrectSyntaxErrors(File dir) { + File errors = new File(dir, "errors"); + File source = new File(dir, "source.wdl"); + String actual = null; + + try { + CompositeTask ctask = getCompositeTask(source); + } catch (SyntaxError syntax_error) { + actual = syntax_error.toString(); + } + + if ( !errors.exists() ) { + try { + FileWriter out = new FileWriter(errors); + out.write(actual); + out.close(); + } catch (IOException error) { + Assert.fail("Could not write errors file: " + error); + } + + System.out.println("Created " + errors); + } + + try { + String expected = Utility.readFile(errors.getAbsolutePath()); + Assert.assertEquals(actual, expected, "Syntax errors did not match"); + } catch (IOException error) { + Assert.fail("Cannot read " + errors.getAbsolutePath()); + } + } +} diff --git a/test-files/parsing/0/ast b/test-files/parsing/0/ast new file mode 100644 index 0000000..2e81e71 --- /dev/null +++ b/test-files/parsing/0/ast @@ -0,0 +1,194 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/0/formatted b/test-files/parsing/0/formatted index ec388cd..64babc5 100644 --- a/test-files/parsing/0/formatted +++ b/test-files/parsing/0/formatted @@ -3,14 +3,14 @@ composite_task foo { output: File("foo.txt") as x; } for ( item in foo ) { - step ctask[version=0] { - input: p0=x, p1=item, p2=y; - output: File("quux.txt") as z; - } step btask[version=0] { input: p0=x, p1=item, p2=GLOBAL; output: File("bar.txt") as y; } + step ctask[version=0] { + input: p0=x, p1=item, p2=y; + output: File("quux.txt") as z; + } } step dtask[version=0] { input: p0=x, p1=y, p2=z; diff --git a/test-files/parsing/0/parsetree b/test-files/parsing/0/parsetree new file mode 100644 index 0000000..553f314 --- /dev/null +++ b/test-files/parsing/0/parsetree @@ -0,0 +1,375 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/0/tokens b/test-files/parsing/0/tokens new file mode 100644 index 0000000..308d6b4 --- /dev/null +++ b/test-files/parsing/0/tokens @@ -0,0 +1,128 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "R0xPQkFM"}, + {"terminal": "semi", "line": 9, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 20, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 21, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 21, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 21, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 21, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 21, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 24, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/1/ast b/test-files/parsing/1/ast new file mode 100644 index 0000000..ab7c6a9 --- /dev/null +++ b/test-files/parsing/1/ast @@ -0,0 +1,211 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/1/formatted b/test-files/parsing/1/formatted index 6eb690b..33ae0f6 100644 --- a/test-files/parsing/1/formatted +++ b/test-files/parsing/1/formatted @@ -3,15 +3,15 @@ composite_task foo { output: File("foo.txt") as x; } for ( item in foo ) { - step ctask[version=0] { - input: p0=item, p1=y; - output: File("quux.txt") as z; - } step btask[version=0] { input: p0=item, p1=global; output: File("bar.txt") as y; } - for ( alpha in beta ) { + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + for ( alpha in beta ) { step dtask[version=0] { input: p0=alpha; } diff --git a/test-files/parsing/1/parsetree b/test-files/parsing/1/parsetree new file mode 100644 index 0000000..e27de1f --- /dev/null +++ b/test-files/parsing/1/parsetree @@ -0,0 +1,418 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/1/tokens b/test-files/parsing/1/tokens new file mode 100644 index 0000000..49b2aec --- /dev/null +++ b/test-files/parsing/1/tokens @@ -0,0 +1,143 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 25, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 25, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 26, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 26, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 26, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 27, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/10/ast b/test-files/parsing/10/ast new file mode 100644 index 0000000..bfc0b8c --- /dev/null +++ b/test-files/parsing/10/ast @@ -0,0 +1,14 @@ +(CompositeTask: + name=identifier, + body=[ + (CompositeTask: + name=identifier, + body=[ + (CompositeTask: + name=identifier, + body=[] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/10/formatted b/test-files/parsing/10/formatted new file mode 100644 index 0000000..352e292 --- /dev/null +++ b/test-files/parsing/10/formatted @@ -0,0 +1,6 @@ +composite_task a { + composite_task b { + composite_task c { + } + } +} diff --git a/test-files/parsing/10/parsetree b/test-files/parsing/10/parsetree new file mode 100644 index 0000000..526495e --- /dev/null +++ b/test-files/parsing/10/parsetree @@ -0,0 +1,36 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/10/source.wdl b/test-files/parsing/10/source.wdl new file mode 100644 index 0000000..a12523a --- /dev/null +++ b/test-files/parsing/10/source.wdl @@ -0,0 +1 @@ +composite_task a{composite_task b{composite_task c {}}} diff --git a/test-files/parsing/10/tokens b/test-files/parsing/10/tokens new file mode 100644 index 0000000..800c1bc --- /dev/null +++ b/test-files/parsing/10/tokens @@ -0,0 +1,14 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "YQ=="}, + {"terminal": "lbrace", "line": 1, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "composite_task", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Yg=="}, + {"terminal": "lbrace", "line": 1, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "composite_task", "line": 1, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Yw=="}, + {"terminal": "lbrace", "line": 1, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/11/ast b/test-files/parsing/11/ast new file mode 100644 index 0000000..2e81e71 --- /dev/null +++ b/test-files/parsing/11/ast @@ -0,0 +1,194 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/11/formatted b/test-files/parsing/11/formatted new file mode 100644 index 0000000..64babc5 --- /dev/null +++ b/test-files/parsing/11/formatted @@ -0,0 +1,19 @@ +composite_task foo { + step atask[version=0] { + output: File("foo.txt") as x; + } + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=item, p2=GLOBAL; + output: File("bar.txt") as y; + } + step ctask[version=0] { + input: p0=x, p1=item, p2=y; + output: File("quux.txt") as z; + } + } + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } +} diff --git a/test-files/parsing/11/parsetree b/test-files/parsing/11/parsetree new file mode 100644 index 0000000..553f314 --- /dev/null +++ b/test-files/parsing/11/parsetree @@ -0,0 +1,375 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/11/source.wdl b/test-files/parsing/11/source.wdl new file mode 100644 index 0000000..0989568 --- /dev/null +++ b/test-files/parsing/11/source.wdl @@ -0,0 +1,8 @@ +composite_task foo { + step atask[version=0] {output: File("foo.txt") as x;} + for ( item in foo ) { + step btask[version=0] {input: p0=x, p1=item, p2=GLOBAL; output: File("bar.txt") as y;} + step ctask[version=0] {input: p0=x, p1=item, p2=y; output: File("quux.txt") as z;} + } + step dtask[version=0] {input: p0=x, p1=y, p2=z; output: File("report.txt") as r;} +} diff --git a/test-files/parsing/11/tokens b/test-files/parsing/11/tokens new file mode 100644 index 0000000..76f5064 --- /dev/null +++ b/test-files/parsing/11/tokens @@ -0,0 +1,128 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 2, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 2, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 2, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 2, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 2, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 2, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 2, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 2, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 2, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 2, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 2, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 3, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 4, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 4, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 4, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 4, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 4, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 4, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 4, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 4, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 4, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "R0xPQkFM"}, + {"terminal": "semi", "line": 4, "col": 59, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 4, "col": 61, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 67, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 69, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 73, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 74, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 83, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 85, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 88, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 4, "col": 89, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 90, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 5, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 5, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 5, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 5, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 5, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 5, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 5, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 5, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 5, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 5, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 5, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 5, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 5, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 5, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 5, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 5, "col": 56, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 5, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 5, "col": 64, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 5, "col": 68, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 5, "col": 69, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 5, "col": 79, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 5, "col": 81, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 5, "col": 84, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 5, "col": 85, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 86, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 6, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 7, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 7, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 7, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 7, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 7, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 7, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 7, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 7, "col": 57, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 7, "col": 59, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 7, "col": 63, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 7, "col": 64, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 7, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 7, "col": 78, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 7, "col": 81, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 7, "col": 82, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 7, "col": 83, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/2/ast b/test-files/parsing/2/ast new file mode 100644 index 0000000..2f78fbb --- /dev/null +++ b/test-files/parsing/2/ast @@ -0,0 +1,301 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ), + (CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/2/formatted b/test-files/parsing/2/formatted index cc38fec..77706f7 100644 --- a/test-files/parsing/2/formatted +++ b/test-files/parsing/2/formatted @@ -3,19 +3,19 @@ composite_task foo { output: File("foo.txt") as x; } for ( item in foo ) { - step ctask[version=0] { - input: p0=item, p1=y; - output: File("quux.txt") as z; - } step btask[version=0] { input: p0=item, p1=global; output: File("bar.txt") as y; } - for ( alpha in beta ) { + step ctask[version=0] { + input: p0=item, p1=y; + output: File("quux.txt") as z; + } + for ( alpha in beta ) { step dtask[version=0] { input: p0=y, p1=alpha; } - composite_task foo_sub { + composite_task foo_sub { step etask[version=0] { input: p0=global1, p1=y, p2=alpha; } diff --git a/test-files/parsing/2/parsetree b/test-files/parsing/2/parsetree new file mode 100644 index 0000000..b84accc --- /dev/null +++ b/test-files/parsing/2/parsetree @@ -0,0 +1,584 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/2/tokens b/test-files/parsing/2/tokens new file mode 100644 index 0000000..58b8ba8 --- /dev/null +++ b/test-files/parsing/2/tokens @@ -0,0 +1,197 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "composite_task", "line": 23, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 23, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9vX3N1Yg=="}, + {"terminal": "lbrace", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 24, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZXRhc2s="}, + {"terminal": "lsquare", "line": 24, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 24, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 24, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 24, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 24, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 25, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 25, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 25, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 25, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 25, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 25, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 27, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 27, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZnRhc2s="}, + {"terminal": "lsquare", "line": 27, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 27, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 27, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 27, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 27, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 28, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 28, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 28, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 28, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 28, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "comma", "line": 28, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 28, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 28, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 29, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 31, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 32, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 34, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 34, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 34, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 34, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 34, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 34, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 34, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 34, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 35, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 35, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 35, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 35, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 35, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 35, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 35, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 35, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 35, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 36, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 36, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 36, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 36, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 36, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 36, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 36, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 36, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 36, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 37, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 39, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/3/ast b/test-files/parsing/3/ast new file mode 100644 index 0000000..fd9db57 --- /dev/null +++ b/test-files/parsing/3/ast @@ -0,0 +1,4 @@ +(CompositeTask: + name=identifier, + body=[] +) \ No newline at end of file diff --git a/test-files/parsing/3/parsetree b/test-files/parsing/3/parsetree new file mode 100644 index 0000000..01245bb --- /dev/null +++ b/test-files/parsing/3/parsetree @@ -0,0 +1,14 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/3/source.wdl b/test-files/parsing/3/source.wdl index 5159ed5..93f0f92 100644 --- a/test-files/parsing/3/source.wdl +++ b/test-files/parsing/3/source.wdl @@ -1,3 +1 @@ -composite_task foo { - -} +composite_task foo {} diff --git a/test-files/parsing/3/tokens b/test-files/parsing/3/tokens new file mode 100644 index 0000000..209f814 --- /dev/null +++ b/test-files/parsing/3/tokens @@ -0,0 +1,6 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/4/ast b/test-files/parsing/4/ast new file mode 100644 index 0000000..f52d0bf --- /dev/null +++ b/test-files/parsing/4/ast @@ -0,0 +1,200 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/4/formatted b/test-files/parsing/4/formatted new file mode 100644 index 0000000..08930c2 --- /dev/null +++ b/test-files/parsing/4/formatted @@ -0,0 +1,22 @@ +composite_task foo { + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + step long_task[version=0] { + output: File("bar.txt") as beta; + } + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item.x; + output: File("baz.txt") as gamma; + } + step btask[version=0] { + input: p0=beta, p1=item.y; + output: File("quux.txt") as epsilon; + } + } + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } +} diff --git a/test-files/parsing/4/parsetree b/test-files/parsing/4/parsetree new file mode 100644 index 0000000..c8eb5bb --- /dev/null +++ b/test-files/parsing/4/parsetree @@ -0,0 +1,407 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/4/source.wdl b/test-files/parsing/4/source.wdl new file mode 100644 index 0000000..19e7960 --- /dev/null +++ b/test-files/parsing/4/source.wdl @@ -0,0 +1,28 @@ +composite_task foo { + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item.x; + output: File("baz.txt") as gamma; + } + + step btask[version=0] { + input: p0=beta, p1=item.y; + output: File("quux.txt") as epsilon; + } + } + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + +} diff --git a/test-files/parsing/4/tokens b/test-files/parsing/4/tokens new file mode 100644 index 0000000..4491806 --- /dev/null +++ b/test-files/parsing/4/tokens @@ -0,0 +1,138 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 8, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 8, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 8, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 11, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 11, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 12, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 12, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 12, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 12, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 12, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 12, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 13, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 13, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 13, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 13, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 13, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 13, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 13, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 13, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 14, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 14, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 14, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 14, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 14, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 17, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 17, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 17, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 17, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 17, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 17, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 17, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 17, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 18, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 18, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 18, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 18, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 18, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 18, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 18, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 18, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 19, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 19, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 19, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 19, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 19, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 19, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 19, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 21, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 23, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 23, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 23, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 23, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 23, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 23, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 23, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 24, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 24, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 24, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 24, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 24, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 24, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 24, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 24, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 25, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 25, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 25, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 25, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 26, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 28, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/5/ast b/test-files/parsing/5/ast new file mode 100644 index 0000000..6288f49 --- /dev/null +++ b/test-files/parsing/5/ast @@ -0,0 +1,206 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/5/formatted b/test-files/parsing/5/formatted new file mode 100644 index 0000000..419c800 --- /dev/null +++ b/test-files/parsing/5/formatted @@ -0,0 +1,24 @@ +composite_task foo { + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + step long_task[version=0] { + output: File("bar.txt") as beta; + } + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item.x; + output: File("baz.txt") as gamma; + } + } + for ( item in items ) { + step btask[version=0] { + input: p0=beta, p2=item.y; + output: File("quux.txt") as epsilon; + } + } + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } +} diff --git a/test-files/parsing/5/parsetree b/test-files/parsing/5/parsetree new file mode 100644 index 0000000..a011c3e --- /dev/null +++ b/test-files/parsing/5/parsetree @@ -0,0 +1,422 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/5/source.wdl b/test-files/parsing/5/source.wdl new file mode 100644 index 0000000..f4d1d88 --- /dev/null +++ b/test-files/parsing/5/source.wdl @@ -0,0 +1,30 @@ +composite_task foo { + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item.x; + output: File("baz.txt") as gamma; + } + } + + for ( item in items ) { + step btask[version=0] { + input: p0=beta, p2=item.y; + output: File("quux.txt") as epsilon; + } + } + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + +} diff --git a/test-files/parsing/5/tokens b/test-files/parsing/5/tokens new file mode 100644 index 0000000..9479da8 --- /dev/null +++ b/test-files/parsing/5/tokens @@ -0,0 +1,146 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 8, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 8, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 8, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 11, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 11, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 12, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 12, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 12, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 12, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 12, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 12, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 13, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 13, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 13, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 13, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 13, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 13, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 13, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 13, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 14, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 14, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 14, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 14, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 14, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 20, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 20, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 21, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 21, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 21, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 21, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 25, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 25, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 26, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 27, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/6/ast b/test-files/parsing/6/ast new file mode 100644 index 0000000..89c8cb8 --- /dev/null +++ b/test-files/parsing/6/ast @@ -0,0 +1,232 @@ +(CompositeTask: + name=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/6/formatted b/test-files/parsing/6/formatted new file mode 100644 index 0000000..3d4f700 --- /dev/null +++ b/test-files/parsing/6/formatted @@ -0,0 +1,28 @@ +composite_task foo { + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item; + output: File("baz.txt") as gamma; + } + } + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + step long_task[version=0] { + output: File("bar.txt") as beta; + } + step batman[version=0] { + } + step robin[version=0] { + } + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + for ( item in items ) { + step btask[version=0] { + input: p0=beta, p1=item; + output: File("quux.txt") as epsilon; + } + } +} diff --git a/test-files/parsing/6/parsetree b/test-files/parsing/6/parsetree new file mode 100644 index 0000000..94826f4 --- /dev/null +++ b/test-files/parsing/6/parsetree @@ -0,0 +1,472 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ) + ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/6/source.wdl b/test-files/parsing/6/source.wdl new file mode 100644 index 0000000..443de10 --- /dev/null +++ b/test-files/parsing/6/source.wdl @@ -0,0 +1,33 @@ +composite_task foo { + + for ( item in items ) { + step atask[version=0] { + input: p0=alpha, p1=item; + output: File("baz.txt") as gamma; + } + } + + step short_task[version=0] { + output: File("foo.txt") as alpha; + } + + step long_task[version=0] { + output: File("bar.txt") as beta; + } + + step batman[version=0] {} + step robin[version=0] {} + + step generate_report[version=0] { + input: p0=gamma, p1=epsilon; + output: File("report.txt") as report; + } + + for ( item in items ) { + step btask[version=0] { + input: p0=beta, p1=item; + output: File("quux.txt") as epsilon; + } + } + +} diff --git a/test-files/parsing/6/tokens b/test-files/parsing/6/tokens new file mode 100644 index 0000000..070200c --- /dev/null +++ b/test-files/parsing/6/tokens @@ -0,0 +1,160 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 3, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 4, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 4, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 4, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 5, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 5, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 5, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 5, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "semi", "line": 5, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 6, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 6, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 6, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 6, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 6, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 6, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 6, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 6, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 6, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 7, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 10, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 10, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 10, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 10, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 10, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 10, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 10, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 11, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 11, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 11, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 11, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 11, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 11, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 11, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 12, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 14, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 15, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 18, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 18, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmF0bWFu"}, + {"terminal": "lsquare", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 18, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 18, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 18, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 18, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cm9iaW4="}, + {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 21, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 21, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 21, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 21, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 21, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 21, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 22, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 22, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 22, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 22, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 22, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 22, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 22, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 22, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 22, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 23, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 23, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 23, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 23, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 23, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 23, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 23, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 23, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 24, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 26, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 26, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 26, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 26, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 26, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 27, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 27, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 27, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 27, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 27, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 27, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 28, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 28, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 28, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 28, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "semi", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 29, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 29, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 29, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 29, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 29, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 29, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 29, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 29, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 29, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 30, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 31, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 33, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/7/ast b/test-files/parsing/7/ast new file mode 100644 index 0000000..9bcd3f0 --- /dev/null +++ b/test-files/parsing/7/ast @@ -0,0 +1,88 @@ +(CompositeTask: + name=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/7/formatted b/test-files/parsing/7/formatted new file mode 100644 index 0000000..0992189 --- /dev/null +++ b/test-files/parsing/7/formatted @@ -0,0 +1,11 @@ +composite_task test { + for ( item in collection ) { + step task[version=0] { + input: p0=x, p1=y, p2=item.z; + output: File("xyz") as list; + } + } + step task1[version=0] { + input: p0=list; + } +} diff --git a/test-files/parsing/7/parsetree b/test-files/parsing/7/parsetree new file mode 100644 index 0000000..bbf5f6b --- /dev/null +++ b/test-files/parsing/7/parsetree @@ -0,0 +1,181 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/7/source.wdl b/test-files/parsing/7/source.wdl new file mode 100644 index 0000000..c4371f6 --- /dev/null +++ b/test-files/parsing/7/source.wdl @@ -0,0 +1,12 @@ +composite_task test { + for (item in collection) { + step task[version=0] { + input: p0=x, p1=y, p2=item.z; + output: File("xyz") as list; + } + } + + step task1[version=0] { + input: p0=list; + } +} diff --git a/test-files/parsing/7/tokens b/test-files/parsing/7/tokens new file mode 100644 index 0000000..3094fbc --- /dev/null +++ b/test-files/parsing/7/tokens @@ -0,0 +1,63 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGVzdA=="}, + {"terminal": "lbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Y29sbGVjdGlvbg=="}, + {"terminal": "rparen", "line": 2, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 4, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 4, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 4, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 4, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 4, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 4, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 4, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 5, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 5, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 5, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 5, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Inh5eiI="}, + {"terminal": "rparen", "line": 5, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 5, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, + {"terminal": "semi", "line": 5, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 9, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGFzazE="}, + {"terminal": "lsquare", "line": 9, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 10, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 10, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 10, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, + {"terminal": "semi", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 12, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/8/ast b/test-files/parsing/8/ast new file mode 100644 index 0000000..f302ae3 --- /dev/null +++ b/test-files/parsing/8/ast @@ -0,0 +1,121 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/8/formatted b/test-files/parsing/8/formatted new file mode 100644 index 0000000..de7a4ce --- /dev/null +++ b/test-files/parsing/8/formatted @@ -0,0 +1,16 @@ +composite_task test { + step s0[version=0] { + output: File("abc") as foo; + } + for ( I in L ) { + for ( J in M ) { + step s1[version=0] { + input: p0=I, p1=J, p2=foo; + output: File("def") as bar; + } + } + } + step s2[version=0] { + input: p0=bar; + } +} diff --git a/test-files/parsing/8/parsetree b/test-files/parsing/8/parsetree new file mode 100644 index 0000000..b9e72b9 --- /dev/null +++ b/test-files/parsing/8/parsetree @@ -0,0 +1,246 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/8/source.wdl b/test-files/parsing/8/source.wdl new file mode 100644 index 0000000..9cfe189 --- /dev/null +++ b/test-files/parsing/8/source.wdl @@ -0,0 +1,18 @@ +composite_task test { + step s0[version=0] { + output: File("abc") as foo; + } + + for (I in L) { + for (J in M) { + step s1[version=0] { + input: p0=I, p1=J, p2=foo; + output: File("def") as bar; + } + } + } + + step s2[version=0] { + input: p0=bar; + } +} diff --git a/test-files/parsing/8/tokens b/test-files/parsing/8/tokens new file mode 100644 index 0000000..a5d3bee --- /dev/null +++ b/test-files/parsing/8/tokens @@ -0,0 +1,87 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dGVzdA=="}, + {"terminal": "lbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czA="}, + {"terminal": "lsquare", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 2, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ImFiYyI="}, + {"terminal": "rparen", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, + {"terminal": "semi", "line": 3, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 6, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 6, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 6, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "SQ=="}, + {"terminal": "in", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 6, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "TA=="}, + {"terminal": "rparen", "line": 6, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 6, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 7, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Sg=="}, + {"terminal": "in", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "TQ=="}, + {"terminal": "rparen", "line": 7, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czE="}, + {"terminal": "lsquare", "line": 8, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "SQ=="}, + {"terminal": "comma", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Sg=="}, + {"terminal": "comma", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 9, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, + {"terminal": "semi", "line": 9, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ImRlZiI="}, + {"terminal": "rparen", "line": 10, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YmFy"}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 13, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 15, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 15, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czI="}, + {"terminal": "lsquare", "line": 15, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 15, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 15, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 15, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 16, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 16, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 16, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YmFy"}, + {"terminal": "semi", "line": 16, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 18, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/9/ast b/test-files/parsing/9/ast new file mode 100644 index 0000000..564d566 --- /dev/null +++ b/test-files/parsing/9/ast @@ -0,0 +1,18 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/9/formatted b/test-files/parsing/9/formatted new file mode 100644 index 0000000..5f0138b --- /dev/null +++ b/test-files/parsing/9/formatted @@ -0,0 +1,4 @@ +composite_task x { + step y[version=0] { + } +} diff --git a/test-files/parsing/9/parsetree b/test-files/parsing/9/parsetree new file mode 100644 index 0000000..e6366b8 --- /dev/null +++ b/test-files/parsing/9/parsetree @@ -0,0 +1,44 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/9/source.wdl b/test-files/parsing/9/source.wdl new file mode 100644 index 0000000..195e03f --- /dev/null +++ b/test-files/parsing/9/source.wdl @@ -0,0 +1 @@ +composite_task x {step y[version=0] {}} diff --git a/test-files/parsing/9/tokens b/test-files/parsing/9/tokens new file mode 100644 index 0000000..463067f --- /dev/null +++ b/test-files/parsing/9/tokens @@ -0,0 +1,15 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 1, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 1, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "eQ=="}, + {"terminal": "lsquare", "line": 1, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 1, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 1, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 1, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 1, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 1, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/syntax-error/0/source.wdl b/test-files/syntax-error/0/source.wdl new file mode 100644 index 0000000..6ac7df5 --- /dev/null +++ b/test-files/syntax-error/0/source.wdl @@ -0,0 +1,24 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + for ( item in foo ) { + step btask[version=0] { + input: p0=x, p1=GLOBAL; + output: File("bar.txt") as y; + } + + step ctask[version=0] { + input: p0=x, p1=y; + output: File("quux.txt") as z; + } + } + + step dtask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as r; + } + +} diff --git a/test-files/syntax-error/1/source.wdl b/test-files/syntax-error/1/source.wdl new file mode 100644 index 0000000..e270d49 --- /dev/null +++ b/test-files/syntax-error/1/source.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x; + } + + step btask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("report.txt") as x; + } + +} diff --git a/test-files/syntax-error/2/source.wdl b/test-files/syntax-error/2/source.wdl new file mode 100644 index 0000000..5213c5b --- /dev/null +++ b/test-files/syntax-error/2/source.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as abc; + } + + step btask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("foo.txt") as xyz; + } + +} diff --git a/test-files/syntax-error/3/source.wdl b/test-files/syntax-error/3/source.wdl new file mode 100644 index 0000000..5674ce3 --- /dev/null +++ b/test-files/syntax-error/3/source.wdl @@ -0,0 +1,12 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as abc; + } + + step atask[version=0] { + input: p0=x, p1=y, p2=z; + output: File("bar.txt") as xyz; + } + +} From 4a691e6fad478fdd90ca232493b68da1e51d1b4a Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 16:05:25 -0500 Subject: [PATCH 115/140] Removing swap file --- .../broadinstitute/compositetask/.ParsingTest.java.swp | Bin 16384 -> 0 bytes .../compositetask/.SyntaxErrorTest.java.swp | Bin 12288 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp delete mode 100644 src/test/java/org/broadinstitute/compositetask/.SyntaxErrorTest.java.swp diff --git a/src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp b/src/test/java/org/broadinstitute/compositetask/.ParsingTest.java.swp deleted file mode 100644 index b8c4ade131d0203fcef6551786f6edf9eca9af1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 Vl;h^=0AQ;wo?ooZj}5^z`47F?L(l*K From 63702d1a09b890202163b178d860c8a157143ea5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Wed, 12 Dec 2012 16:06:05 -0500 Subject: [PATCH 116/140] Adding syntax error tests --- .../java/org/broadinstitute/compositetask/CompositeTask.java | 10 +++++----- .../java/org/broadinstitute/compositetask/SyntaxErrorTest.java | 2 +- test-files/syntax-error/0/errors | 9 +++++++++ test-files/syntax-error/1/errors | 9 +++++++++ test-files/syntax-error/2/errors | 9 +++++++++ test-files/syntax-error/3/errors | 9 +++++++++ 6 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 test-files/syntax-error/0/errors create mode 100644 test-files/syntax-error/1/errors create mode 100644 test-files/syntax-error/2/errors create mode 100644 test-files/syntax-error/3/errors diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 8b4bd55..c7265d8 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -164,15 +164,15 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { for ( AstNode output_node : output_list ) { Ast output = (Ast) output_node; Terminal filepath = (Terminal) output.getAttribute("file"); - Ast output_var = (Ast) output.getAttribute("var"); + Ast step_output = (Ast) output.getAttribute("var"); - CompositeTaskVariable variable = ast_to_variable((Ast) output_var.getAttribute("var")); - Terminal variable_terminal = (Terminal) ((Ast) output.getAttribute("var")).getAttribute("name"); + CompositeTaskVariable variable = ast_to_variable((Ast) step_output.getAttribute("var")); + Terminal variable_terminal = (Terminal) ((Ast) ((Ast) output.getAttribute("var")).getAttribute("var")).getAttribute("name"); String method = null; - if ( output_var.getName().equals("OutputVariable") ) { + if ( step_output.getName().equals("OutputVariable") ) { method = "assign"; - } else if ( output_var.getName().equals("OutputListAppend") ) { + } else if ( step_output.getName().equals("OutputListAppend") ) { method = "append"; } diff --git a/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java index b3ec894..128b5a7 100644 --- a/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java +++ b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java @@ -19,7 +19,7 @@ { @DataProvider(name="syntaxErrorTests") public Object[][] parsingTests() { - File parsingTestDir = new File("test-files", "syntax-errors"); + File parsingTestDir = new File("test-files", "syntax-error"); Collection composite_tasks = new ArrayList(); for ( String subDir : parsingTestDir.list() ) { diff --git a/test-files/syntax-error/0/errors b/test-files/syntax-error/0/errors new file mode 100644 index 0000000..0007b12 --- /dev/null +++ b/test-files/syntax-error/0/errors @@ -0,0 +1,9 @@ +org.broadinstitute.parser.SyntaxError: Step 'btask' inside for loop doesn't use loop iterator: item +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/0/source.wdl @ line 8, column 10: + + step btask[version=0] { + ^ +Loop iterator is declared @ line 7, column 9: + + for ( item in foo ) { + ^ diff --git a/test-files/syntax-error/1/errors b/test-files/syntax-error/1/errors new file mode 100644 index 0000000..938fcda --- /dev/null +++ b/test-files/syntax-error/1/errors @@ -0,0 +1,9 @@ +org.broadinstitute.parser.SyntaxError: Two steps output to the same variable: x +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/1/source.wdl @ line 9, column 35: + + output: File("report.txt") as x; + ^ +Previous output for variable was @ line 4, column 32: + + output: File("foo.txt") as x; + ^ diff --git a/test-files/syntax-error/2/errors b/test-files/syntax-error/2/errors new file mode 100644 index 0000000..278b082 --- /dev/null +++ b/test-files/syntax-error/2/errors @@ -0,0 +1,9 @@ +org.broadinstitute.parser.SyntaxError: Two steps output to the same file: "foo.txt" +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/2/source.wdl @ line 9, column 18: + + output: File("foo.txt") as xyz; + ^ +Previous output for file was @ line 4, column 18: + + output: File("foo.txt") as abc; + ^ diff --git a/test-files/syntax-error/3/errors b/test-files/syntax-error/3/errors new file mode 100644 index 0000000..d05934b --- /dev/null +++ b/test-files/syntax-error/3/errors @@ -0,0 +1,9 @@ +org.broadinstitute.parser.SyntaxError: Two steps have the same name: atask +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/3/source.wdl @ line 7, column 8: + + step atask[version=0] { + ^ +Previous step was defined @ line 3, column 8: + + step atask[version=0] { + ^ From 16a6035b330a4e7f05e624f143c7a4a9e90be0ce Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 13 Dec 2012 09:31:58 -0500 Subject: [PATCH 117/140] Adding graph generation tests --- .../compositetask/CompositeTask.java | 4 + .../compositetask/CompositeTaskEdge.java | 6 +- .../compositetask/CompositeTaskForLoop.java | 4 + .../compositetask/CompositeTaskScope.java | 1 + .../compositetask/CompositeTaskStep.java | 4 + .../compositetask/CompositeTaskVariable.java | 4 + .../compositetask/CompositeTaskVertex.java | 2 +- .../broadinstitute/compositetask/ParsingTest.java | 12 ++- test-files/parsing/0/graph | 81 +++++++++++++++++++ test-files/parsing/1/graph | 89 +++++++++++++++++++++ test-files/parsing/10/graph | 5 ++ test-files/parsing/11/graph | 81 +++++++++++++++++++ test-files/parsing/2/graph | 93 ++++++++++++++++++++++ test-files/parsing/3/graph | 5 ++ test-files/parsing/4/graph | 76 ++++++++++++++++++ test-files/parsing/5/graph | 89 +++++++++++++++++++++ test-files/parsing/6/graph | 89 +++++++++++++++++++++ test-files/parsing/7/graph | 46 +++++++++++ test-files/parsing/8/graph | 60 ++++++++++++++ test-files/parsing/9/graph | 6 ++ 20 files changed, 752 insertions(+), 5 deletions(-) create mode 100644 test-files/parsing/0/graph create mode 100644 test-files/parsing/1/graph create mode 100644 test-files/parsing/10/graph create mode 100644 test-files/parsing/11/graph create mode 100644 test-files/parsing/2/graph create mode 100644 test-files/parsing/3/graph create mode 100644 test-files/parsing/4/graph create mode 100644 test-files/parsing/5/graph create mode 100644 test-files/parsing/6/graph create mode 100644 test-files/parsing/7/graph create mode 100644 test-files/parsing/8/graph create mode 100644 test-files/parsing/9/graph diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index c7265d8..587068a 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -348,6 +348,10 @@ public boolean contains(CompositeTaskNode node) { return false; } + public int compareTo(CompositeTaskVertex other) { + return this.toString().compareTo(other.toString()); + } + public String toString() { return "[CompositeTask name="+this.name+"]"; } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java index 818b1a5..0ae13c4 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskEdge.java @@ -1,6 +1,6 @@ package org.broadinstitute.compositetask; -public class CompositeTaskEdge { +public class CompositeTaskEdge implements Comparable { private CompositeTaskVertex start; private CompositeTaskVertex end; @@ -25,6 +25,10 @@ public void setEnd(CompositeTaskVertex end) { this.end = end; } + public int compareTo(CompositeTaskEdge other) { + return this.toString().compareTo(other.toString()); + } + public String toString() { return "[Edge\n from: "+this.start+"\n to: "+this.end+"\n]"; } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java index 41cea93..36cedc2 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskForLoop.java @@ -42,6 +42,10 @@ public CompositeTaskScope getParent() { return this.parent; } + public int compareTo(CompositeTaskVertex other) { + return this.toString().compareTo(other.toString()); + } + public boolean contains(CompositeTaskNode node) { for ( CompositeTaskNode sub_node : this.nodes ) { if ( node.equals(sub_node) ) { diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java index 53bb245..ec172c7 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskScope.java @@ -5,4 +5,5 @@ public interface CompositeTaskScope extends CompositeTaskNode, CompositeTaskVertex { public Set getNodes(); public boolean contains(CompositeTaskNode node); + public int compareTo(CompositeTaskVertex other); } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java index 3a0ee94..987bb4b 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStep.java @@ -55,6 +55,10 @@ public boolean equals(CompositeTaskStep other) { return false; } + public int compareTo(CompositeTaskVertex other) { + return this.toString().compareTo(other.toString()); + } + public String toString() { return "[Step: name=" + this.name + "]"; } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java index d5af2e1..a40de2e 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVariable.java @@ -33,6 +33,10 @@ public int hashCode() { return 0; } + public int compareTo(CompositeTaskVertex other) { + return this.toString().compareTo(other.toString()); + } + public boolean equals(CompositeTaskVariable other) { if ( other.getName().equals(this.name) ) { if ( other.getMember() == null && this.member == null ) { diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java index e463b91..0c1af8e 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskVertex.java @@ -1,3 +1,3 @@ package org.broadinstitute.compositetask; -public interface CompositeTaskVertex {} +public interface CompositeTaskVertex extends Comparable {} diff --git a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java index 45cff01..cb678f8 100644 --- a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java @@ -167,7 +167,13 @@ public void testSourceFormatterOutputsCorrectlyFormattedSourceCode(File dir) { } } - @Test(dataProvider="parsingTests", enabled=false) + public static > List asSortedList(Collection c) { + List list = new ArrayList(c); + java.util.Collections.sort(list); + return list; + } + + @Test(dataProvider="parsingTests") public void testCompositeTaskGeneratesCorrectGraph(File dir) { File source = new File(dir, "source.wdl"); File graph_file = new File(dir, "graph"); @@ -177,14 +183,14 @@ public void testCompositeTaskGeneratesCorrectGraph(File dir) { StringBuilder actual = new StringBuilder(); actual.append("VERTICIES\n"); actual.append("---------\n"); - for ( CompositeTaskVertex v : graph.vertexSet() ) { + for ( CompositeTaskVertex v : asSortedList(graph.vertexSet()) ) { actual.append(v + "\n"); } actual.append("\n"); actual.append("EDGES\n"); actual.append("-----\n"); - for ( CompositeTaskEdge v : graph.edgeSet() ) { + for ( CompositeTaskEdge v : asSortedList(graph.edgeSet()) ) { actual.append(v + "\n"); } diff --git a/test-files/parsing/0/graph b/test-files/parsing/0/graph new file mode 100644 index 0000000..42e580c --- /dev/null +++ b/test-files/parsing/0/graph @@ -0,0 +1,81 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] +[Step: name=atask] +[Step: name=btask] +[Step: name=ctask] +[Step: name=dtask] +[Variable: name=GLOBAL] +[Variable: name=foo] +[Variable: name=item] +[Variable: name=r] +[Variable: name=x] +[Variable: name=y] +[Variable: name=z] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] + to: [Step: name=dtask] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=x] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=y] +] +[Edge + from: [Step: name=ctask] + to: [Variable: name=z] +] +[Edge + from: [Step: name=dtask] + to: [Variable: name=r] +] +[Edge + from: [Variable: name=GLOBAL] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=foo] + to: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] +] +[Edge + from: [Variable: name=item] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=z] + to: [Step: name=dtask] +] diff --git a/test-files/parsing/1/graph b/test-files/parsing/1/graph new file mode 100644 index 0000000..e659dbb --- /dev/null +++ b/test-files/parsing/1/graph @@ -0,0 +1,89 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] +[Step: name=atask] +[Step: name=btask] +[Step: name=ctask] +[Step: name=dtask] +[Step: name=gtask] +[Variable: name=alpha] +[Variable: name=beta] +[Variable: name=foo] +[Variable: name=global] +[Variable: name=item] +[Variable: name=r] +[Variable: name=x] +[Variable: name=y] +[Variable: name=z] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=1] + to: [Variable: name=alpha] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] + to: [Step: name=gtask] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=x] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=y] +] +[Edge + from: [Step: name=ctask] + to: [Variable: name=z] +] +[Edge + from: [Step: name=gtask] + to: [Variable: name=r] +] +[Edge + from: [Variable: name=alpha] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=beta] + to: [CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=1] +] +[Edge + from: [Variable: name=foo] + to: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] +] +[Edge + from: [Variable: name=global] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=gtask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=gtask] +] +[Edge + from: [Variable: name=z] + to: [Step: name=gtask] +] diff --git a/test-files/parsing/10/graph b/test-files/parsing/10/graph new file mode 100644 index 0000000..d612dd1 --- /dev/null +++ b/test-files/parsing/10/graph @@ -0,0 +1,5 @@ +VERTICIES +--------- + +EDGES +----- diff --git a/test-files/parsing/11/graph b/test-files/parsing/11/graph new file mode 100644 index 0000000..42e580c --- /dev/null +++ b/test-files/parsing/11/graph @@ -0,0 +1,81 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] +[Step: name=atask] +[Step: name=btask] +[Step: name=ctask] +[Step: name=dtask] +[Variable: name=GLOBAL] +[Variable: name=foo] +[Variable: name=item] +[Variable: name=r] +[Variable: name=x] +[Variable: name=y] +[Variable: name=z] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] + to: [Step: name=dtask] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=x] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=y] +] +[Edge + from: [Step: name=ctask] + to: [Variable: name=z] +] +[Edge + from: [Step: name=dtask] + to: [Variable: name=r] +] +[Edge + from: [Variable: name=GLOBAL] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=foo] + to: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=2] +] +[Edge + from: [Variable: name=item] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=z] + to: [Step: name=dtask] +] diff --git a/test-files/parsing/2/graph b/test-files/parsing/2/graph new file mode 100644 index 0000000..728028e --- /dev/null +++ b/test-files/parsing/2/graph @@ -0,0 +1,93 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=2] +[CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] +[Step: name=atask] +[Step: name=btask] +[Step: name=ctask] +[Step: name=dtask] +[Step: name=gtask] +[Variable: name=alpha] +[Variable: name=beta] +[Variable: name=foo] +[Variable: name=global] +[Variable: name=item] +[Variable: name=r] +[Variable: name=x] +[Variable: name=y] +[Variable: name=z] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=2] + to: [Variable: name=alpha] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] + to: [Step: name=gtask] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=x] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=y] +] +[Edge + from: [Step: name=ctask] + to: [Variable: name=z] +] +[Edge + from: [Step: name=gtask] + to: [Variable: name=r] +] +[Edge + from: [Variable: name=alpha] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=beta] + to: [CompositeTaskForScope: collection=[Variable: name=beta], var=[Variable: name=alpha], # nodes=2] +] +[Edge + from: [Variable: name=foo] + to: [CompositeTaskForScope: collection=[Variable: name=foo], var=[Variable: name=item], # nodes=3] +] +[Edge + from: [Variable: name=global] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=x] + to: [Step: name=gtask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=ctask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=dtask] +] +[Edge + from: [Variable: name=y] + to: [Step: name=gtask] +] +[Edge + from: [Variable: name=z] + to: [Step: name=gtask] +] diff --git a/test-files/parsing/3/graph b/test-files/parsing/3/graph new file mode 100644 index 0000000..d612dd1 --- /dev/null +++ b/test-files/parsing/3/graph @@ -0,0 +1,5 @@ +VERTICIES +--------- + +EDGES +----- diff --git a/test-files/parsing/4/graph b/test-files/parsing/4/graph new file mode 100644 index 0000000..bf0f29a --- /dev/null +++ b/test-files/parsing/4/graph @@ -0,0 +1,76 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=2] +[Step: name=atask] +[Step: name=btask] +[Step: name=generate_report] +[Step: name=long_task] +[Step: name=short_task] +[Variable: name=alpha] +[Variable: name=beta] +[Variable: name=epsilon] +[Variable: name=gamma] +[Variable: name=item, member=x] +[Variable: name=item, member=y] +[Variable: name=item] +[Variable: name=items] +[Variable: name=report] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=2] + to: [Step: name=generate_report] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=2] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=gamma] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=epsilon] +] +[Edge + from: [Step: name=generate_report] + to: [Variable: name=report] +] +[Edge + from: [Step: name=long_task] + to: [Variable: name=beta] +] +[Edge + from: [Step: name=short_task] + to: [Variable: name=alpha] +] +[Edge + from: [Variable: name=alpha] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=beta] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=epsilon] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=gamma] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=item, member=x] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=item, member=y] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=items] + to: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=2] +] diff --git a/test-files/parsing/5/graph b/test-files/parsing/5/graph new file mode 100644 index 0000000..738a48e --- /dev/null +++ b/test-files/parsing/5/graph @@ -0,0 +1,89 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +[Step: name=atask] +[Step: name=btask] +[Step: name=generate_report] +[Step: name=long_task] +[Step: name=short_task] +[Variable: name=alpha] +[Variable: name=beta] +[Variable: name=epsilon] +[Variable: name=gamma] +[Variable: name=item, member=x] +[Variable: name=item, member=y] +[Variable: name=item] +[Variable: name=items] +[Variable: name=report] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Step: name=generate_report] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Step: name=generate_report] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Variable: name=item] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=gamma] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=epsilon] +] +[Edge + from: [Step: name=generate_report] + to: [Variable: name=report] +] +[Edge + from: [Step: name=long_task] + to: [Variable: name=beta] +] +[Edge + from: [Step: name=short_task] + to: [Variable: name=alpha] +] +[Edge + from: [Variable: name=alpha] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=beta] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=epsilon] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=gamma] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=item, member=x] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=item, member=y] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=items] + to: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +] +[Edge + from: [Variable: name=items] + to: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +] diff --git a/test-files/parsing/6/graph b/test-files/parsing/6/graph new file mode 100644 index 0000000..f95f44f --- /dev/null +++ b/test-files/parsing/6/graph @@ -0,0 +1,89 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +[Step: name=atask] +[Step: name=batman] +[Step: name=btask] +[Step: name=generate_report] +[Step: name=long_task] +[Step: name=robin] +[Step: name=short_task] +[Variable: name=alpha] +[Variable: name=beta] +[Variable: name=epsilon] +[Variable: name=gamma] +[Variable: name=item] +[Variable: name=items] +[Variable: name=report] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Step: name=generate_report] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Step: name=generate_report] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Variable: name=item] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] + to: [Variable: name=item] +] +[Edge + from: [Step: name=atask] + to: [Variable: name=gamma] +] +[Edge + from: [Step: name=btask] + to: [Variable: name=epsilon] +] +[Edge + from: [Step: name=generate_report] + to: [Variable: name=report] +] +[Edge + from: [Step: name=long_task] + to: [Variable: name=beta] +] +[Edge + from: [Step: name=short_task] + to: [Variable: name=alpha] +] +[Edge + from: [Variable: name=alpha] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=beta] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=epsilon] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=gamma] + to: [Step: name=generate_report] +] +[Edge + from: [Variable: name=item] + to: [Step: name=atask] +] +[Edge + from: [Variable: name=item] + to: [Step: name=btask] +] +[Edge + from: [Variable: name=items] + to: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +] +[Edge + from: [Variable: name=items] + to: [CompositeTaskForScope: collection=[Variable: name=items], var=[Variable: name=item], # nodes=1] +] diff --git a/test-files/parsing/7/graph b/test-files/parsing/7/graph new file mode 100644 index 0000000..1e8a0a4 --- /dev/null +++ b/test-files/parsing/7/graph @@ -0,0 +1,46 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=collection], var=[Variable: name=item], # nodes=1] +[Step: name=task1] +[Step: name=task] +[Variable: name=collection] +[Variable: name=item, member=z] +[Variable: name=item] +[Variable: name=list] +[Variable: name=x] +[Variable: name=y] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=collection], var=[Variable: name=item], # nodes=1] + to: [Step: name=task1] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=collection], var=[Variable: name=item], # nodes=1] + to: [Variable: name=item] +] +[Edge + from: [Step: name=task] + to: [Variable: name=list] +] +[Edge + from: [Variable: name=collection] + to: [CompositeTaskForScope: collection=[Variable: name=collection], var=[Variable: name=item], # nodes=1] +] +[Edge + from: [Variable: name=item, member=z] + to: [Step: name=task] +] +[Edge + from: [Variable: name=list] + to: [Step: name=task1] +] +[Edge + from: [Variable: name=x] + to: [Step: name=task] +] +[Edge + from: [Variable: name=y] + to: [Step: name=task] +] diff --git a/test-files/parsing/8/graph b/test-files/parsing/8/graph new file mode 100644 index 0000000..50cd25b --- /dev/null +++ b/test-files/parsing/8/graph @@ -0,0 +1,60 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] +[Step: name=s0] +[Step: name=s1] +[Step: name=s2] +[Variable: name=I] +[Variable: name=J] +[Variable: name=L] +[Variable: name=M] +[Variable: name=bar] +[Variable: name=foo] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Step: name=s2] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] + to: [Variable: name=I] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] + to: [Variable: name=J] +] +[Edge + from: [Step: name=s0] + to: [Variable: name=foo] +] +[Edge + from: [Step: name=s1] + to: [Variable: name=bar] +] +[Edge + from: [Variable: name=I] + to: [Step: name=s1] +] +[Edge + from: [Variable: name=J] + to: [Step: name=s1] +] +[Edge + from: [Variable: name=L] + to: [CompositeTaskForScope: collection=[Variable: name=L], var=[Variable: name=I], # nodes=1] +] +[Edge + from: [Variable: name=M] + to: [CompositeTaskForScope: collection=[Variable: name=M], var=[Variable: name=J], # nodes=1] +] +[Edge + from: [Variable: name=bar] + to: [Step: name=s2] +] +[Edge + from: [Variable: name=foo] + to: [Step: name=s1] +] diff --git a/test-files/parsing/9/graph b/test-files/parsing/9/graph new file mode 100644 index 0000000..c4e467e --- /dev/null +++ b/test-files/parsing/9/graph @@ -0,0 +1,6 @@ +VERTICIES +--------- +[Step: name=y] + +EDGES +----- From e05b829a944641c4fb60c5185fb5e435dd28222c Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 13 Dec 2012 11:14:53 -0500 Subject: [PATCH 118/140] unit test fixes and additions --- .../org/broadinstitute/compositetask/Lexer.java | 27 +- .../broadinstitute/compositetask/ParsingTest.java | 6 +- test-files/parsing/12/ast | 167 ++++++++++ test-files/parsing/12/formatted | 18 ++ test-files/parsing/12/graph | 69 ++++ test-files/parsing/12/parsetree | 348 ++++++++++++++++++++ test-files/parsing/12/source.wdl | 18 ++ test-files/parsing/12/tokens | 119 +++++++ test-files/parsing/13/ast | 35 ++ test-files/parsing/13/formatted | 10 + test-files/parsing/13/graph | 39 +++ test-files/parsing/13/parsetree | 89 ++++++ test-files/parsing/13/source.wdl | 4 + test-files/parsing/13/tokens | 39 +++ test-files/parsing/14/ast | 186 +++++++++++ test-files/parsing/14/formatted | 13 + test-files/parsing/14/graph | 76 +++++ test-files/parsing/14/parsetree | 354 +++++++++++++++++++++ test-files/parsing/14/source.wdl | 27 ++ test-files/parsing/14/tokens | 126 ++++++++ test-files/parsing/15/ast | 4 + test-files/parsing/15/formatted | 2 + test-files/parsing/15/graph | 5 + test-files/parsing/15/parsetree | 14 + test-files/parsing/15/source.wdl | 4 + test-files/parsing/15/tokens | 6 + test-files/parsing/16/ast | 18 ++ test-files/parsing/16/formatted | 4 + test-files/parsing/16/graph | 6 + test-files/parsing/16/parsetree | 44 +++ test-files/parsing/16/source.wdl | 11 + test-files/parsing/16/tokens | 15 + test-files/parsing/17/ast | 94 ++++++ test-files/parsing/17/formatted | 12 + test-files/parsing/17/graph | 42 +++ test-files/parsing/17/parsetree | 195 ++++++++++++ test-files/parsing/17/source.wdl | 10 + test-files/parsing/17/tokens | 68 ++++ test-files/syntax-error/4/errors | 5 + test-files/syntax-error/4/source.wdl | 4 + test-files/syntax-error/5/errors | 6 + test-files/syntax-error/5/source.wdl | 1 + 42 files changed, 2327 insertions(+), 13 deletions(-) create mode 100644 test-files/parsing/12/ast create mode 100644 test-files/parsing/12/formatted create mode 100644 test-files/parsing/12/graph create mode 100644 test-files/parsing/12/parsetree create mode 100644 test-files/parsing/12/source.wdl create mode 100644 test-files/parsing/12/tokens create mode 100644 test-files/parsing/13/ast create mode 100644 test-files/parsing/13/formatted create mode 100644 test-files/parsing/13/graph create mode 100644 test-files/parsing/13/parsetree create mode 100644 test-files/parsing/13/source.wdl create mode 100644 test-files/parsing/13/tokens create mode 100644 test-files/parsing/14/ast create mode 100644 test-files/parsing/14/formatted create mode 100644 test-files/parsing/14/graph create mode 100644 test-files/parsing/14/parsetree create mode 100644 test-files/parsing/14/source.wdl create mode 100644 test-files/parsing/14/tokens create mode 100644 test-files/parsing/15/ast create mode 100644 test-files/parsing/15/formatted create mode 100644 test-files/parsing/15/graph create mode 100644 test-files/parsing/15/parsetree create mode 100644 test-files/parsing/15/source.wdl create mode 100644 test-files/parsing/15/tokens create mode 100644 test-files/parsing/16/ast create mode 100644 test-files/parsing/16/formatted create mode 100644 test-files/parsing/16/graph create mode 100644 test-files/parsing/16/parsetree create mode 100644 test-files/parsing/16/source.wdl create mode 100644 test-files/parsing/16/tokens create mode 100644 test-files/parsing/17/ast create mode 100644 test-files/parsing/17/formatted create mode 100644 test-files/parsing/17/graph create mode 100644 test-files/parsing/17/parsetree create mode 100644 test-files/parsing/17/source.wdl create mode 100644 test-files/parsing/17/tokens create mode 100644 test-files/syntax-error/4/errors create mode 100644 test-files/syntax-error/4/source.wdl create mode 100644 test-files/syntax-error/5/errors create mode 100644 test-files/syntax-error/5/source.wdl diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index 01e1957..2314da5 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -35,7 +35,6 @@ LexerMatch match(SourceCode source) { LexerMatch rval = null; if ( m.find() ) { String sourceString = m.group(); - if (this.terminal != null) rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), sourceString, source.getResource(), source.getLine(), source.getColumn())); else @@ -45,6 +44,10 @@ LexerMatch match(SourceCode source) { } return rval; } + + public String toString() { + return "[TokenLexer regex="+regex+", terminal="+terminal+"]"; + } } public class Lexer { @@ -53,17 +56,17 @@ LexerMatch match(SourceCode source) { Lexer() { this.regex = new ArrayList(); - this.regex.add( new TokenLexer(Pattern.compile("\\/\\*.*?\\*\\/", Pattern.DOTALL), null) ); - this.regex.add( new TokenLexer(Pattern.compile("//.*"), null) ); - this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); - this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); - this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); - this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); - this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); - this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); - this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) ); - this.regex.add( new TokenLexer(Pattern.compile("^into(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INTO) ); - this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_IN) ); + this.regex.add( new TokenLexer(Pattern.compile("^/\\*.*?\\*/", Pattern.DOTALL), null) ); + this.regex.add( new TokenLexer(Pattern.compile("^//.*"), null) ); + this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); + this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); + this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); + this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); + this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) ); + this.regex.add( new TokenLexer(Pattern.compile("^into(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INTO) ); + this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_IN) ); this.regex.add( new TokenLexer(Pattern.compile("^\\."), CompositeTaskParser.TerminalId.TERMINAL_DOT) ); this.regex.add( new TokenLexer(Pattern.compile("^,"), CompositeTaskParser.TerminalId.TERMINAL_COMMA) ); this.regex.add( new TokenLexer(Pattern.compile("^:"), CompositeTaskParser.TerminalId.TERMINAL_COLON) ); diff --git a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java index cb678f8..8474d87 100644 --- a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java @@ -28,7 +28,11 @@ Collection composite_tasks = new ArrayList(); for ( String subDir : parsingTestDir.list() ) { - composite_tasks.add(new Object[] { new File(parsingTestDir, subDir) }); + File testDir = new File(parsingTestDir, subDir); + File skipFile = new File(testDir, "skip"); + if ( ! skipFile.exists() ) { + composite_tasks.add(new Object[] { testDir }); + } } return composite_tasks.toArray(new Object[0][]); diff --git a/test-files/parsing/12/ast b/test-files/parsing/12/ast new file mode 100644 index 0000000..8bf9f9a --- /dev/null +++ b/test-files/parsing/12/ast @@ -0,0 +1,167 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputListAppend: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputListAppend: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/12/formatted b/test-files/parsing/12/formatted new file mode 100644 index 0000000..c61cb0d --- /dev/null +++ b/test-files/parsing/12/formatted @@ -0,0 +1,18 @@ +composite_task CopyNumberQC { + step LaneBlackList[version=6] { + output: File("lane_blacklist.txt") as lane_blacklist; + } + for ( sample in samples ) { + step RegionCovPerLane[version=16] { + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.rcl") as rcl; + } + step MakeLaneList[version=11] { + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.lanelist") as lanelist; + } + } + step CopyNumberQC[version=25] { + input: lanes_list=lanelist, rcl_list=rcl, lane_blacklist=lane_blacklist; + } +} diff --git a/test-files/parsing/12/graph b/test-files/parsing/12/graph new file mode 100644 index 0000000..132941f --- /dev/null +++ b/test-files/parsing/12/graph @@ -0,0 +1,69 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=samples], var=[Variable: name=sample], # nodes=2] +[Step: name=CopyNumberQC] +[Step: name=LaneBlackList] +[Step: name=MakeLaneList] +[Step: name=RegionCovPerLane] +[Variable: name=lane_blacklist] +[Variable: name=lanelist] +[Variable: name=rcl] +[Variable: name=sample, member=bam] +[Variable: name=sample, member=id] +[Variable: name=sample] +[Variable: name=samples] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=samples], var=[Variable: name=sample], # nodes=2] + to: [Step: name=CopyNumberQC] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=samples], var=[Variable: name=sample], # nodes=2] + to: [Variable: name=sample] +] +[Edge + from: [Step: name=LaneBlackList] + to: [Variable: name=lane_blacklist] +] +[Edge + from: [Step: name=MakeLaneList] + to: [Variable: name=lanelist] +] +[Edge + from: [Step: name=RegionCovPerLane] + to: [Variable: name=rcl] +] +[Edge + from: [Variable: name=lane_blacklist] + to: [Step: name=CopyNumberQC] +] +[Edge + from: [Variable: name=lanelist] + to: [Step: name=CopyNumberQC] +] +[Edge + from: [Variable: name=rcl] + to: [Step: name=CopyNumberQC] +] +[Edge + from: [Variable: name=sample, member=bam] + to: [Step: name=MakeLaneList] +] +[Edge + from: [Variable: name=sample, member=bam] + to: [Step: name=RegionCovPerLane] +] +[Edge + from: [Variable: name=sample, member=id] + to: [Step: name=MakeLaneList] +] +[Edge + from: [Variable: name=sample, member=id] + to: [Step: name=RegionCovPerLane] +] +[Edge + from: [Variable: name=samples] + to: [CompositeTaskForScope: collection=[Variable: name=samples], var=[Variable: name=sample], # nodes=2] +] diff --git a/test-files/parsing/12/parsetree b/test-files/parsing/12/parsetree new file mode 100644 index 0000000..e1fe201 --- /dev/null +++ b/test-files/parsing/12/parsetree @@ -0,0 +1,348 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + into, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + into, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/12/source.wdl b/test-files/parsing/12/source.wdl new file mode 100644 index 0000000..7200425 --- /dev/null +++ b/test-files/parsing/12/source.wdl @@ -0,0 +1,18 @@ +composite_task CopyNumberQC { + step LaneBlackList[version=6] { + output: File("lane_blacklist.txt") as lane_blacklist; + } + for ( sample in samples ) { + step RegionCovPerLane[version=16] { + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.rcl") into rcl; + } + step MakeLaneList[version=11] { + input: bam_file=sample.bam, sample_id=sample.id; + output: File("${sample.id}.lanelist") into lanelist; + } + } + step CopyNumberQC[version=25] { + input: lanes_list=lanelist, rcl_list=rcl, lane_blacklist=lane_blacklist; + } +} diff --git a/test-files/parsing/12/tokens b/test-files/parsing/12/tokens new file mode 100644 index 0000000..8cb9819 --- /dev/null +++ b/test-files/parsing/12/tokens @@ -0,0 +1,119 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, + {"terminal": "lbrace", "line": 1, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "TGFuZUJsYWNrTGlzdA=="}, + {"terminal": "lsquare", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ng=="}, + {"terminal": "rsquare", "line": 2, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ImxhbmVfYmxhY2tsaXN0LnR4dCI="}, + {"terminal": "rparen", "line": 3, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "semi", "line": 3, "col": 57, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 5, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "in", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 5, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlcw=="}, + {"terminal": "rparen", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 5, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "UmVnaW9uQ292UGVyTGFuZQ=="}, + {"terminal": "lsquare", "line": 6, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 6, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 6, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 6, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MTY="}, + {"terminal": "rsquare", "line": 6, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 6, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, + {"terminal": "assign", "line": 7, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFt"}, + {"terminal": "comma", "line": 7, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, + {"terminal": "assign", "line": 7, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 7, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aWQ="}, + {"terminal": "semi", "line": 7, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 8, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5yY2wi"}, + {"terminal": "rparen", "line": 8, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 8, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 8, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNs"}, + {"terminal": "semi", "line": 8, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 10, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "TWFrZUxhbmVMaXN0"}, + {"terminal": "lsquare", "line": 10, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 10, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 10, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MTE="}, + {"terminal": "rsquare", "line": 10, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 11, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, + {"terminal": "assign", "line": 11, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 11, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 11, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFt"}, + {"terminal": "comma", "line": 11, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 11, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, + {"terminal": "assign", "line": 11, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 11, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 11, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 11, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aWQ="}, + {"terminal": "semi", "line": 11, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 12, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 12, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 12, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 12, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5sYW5lbGlzdCI="}, + {"terminal": "rparen", "line": 12, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 12, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 12, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, + {"terminal": "semi", "line": 12, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 15, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 15, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, + {"terminal": "lsquare", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 15, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 15, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 15, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MjU="}, + {"terminal": "rsquare", "line": 15, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 15, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 16, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 16, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZXNfbGlzdA=="}, + {"terminal": "assign", "line": 16, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, + {"terminal": "comma", "line": 16, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 16, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNsX2xpc3Q="}, + {"terminal": "assign", "line": 16, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNs"}, + {"terminal": "comma", "line": 16, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 16, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "assign", "line": 16, "col": 61, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "semi", "line": 16, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 18, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/13/ast b/test-files/parsing/13/ast new file mode 100644 index 0000000..9ca8027 --- /dev/null +++ b/test-files/parsing/13/ast @@ -0,0 +1,35 @@ +(CompositeTask: + name=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (ForLoop: + collection=identifier, + item=identifier, + body=[] + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/13/formatted b/test-files/parsing/13/formatted new file mode 100644 index 0000000..5624645 --- /dev/null +++ b/test-files/parsing/13/formatted @@ -0,0 +1,10 @@ +composite_task foo { + for ( a in b ) { + for ( c in d ) { + for ( e in f ) { + } + } + } + step x[version=1000] { + } +} diff --git a/test-files/parsing/13/graph b/test-files/parsing/13/graph new file mode 100644 index 0000000..3593193 --- /dev/null +++ b/test-files/parsing/13/graph @@ -0,0 +1,39 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=b], var=[Variable: name=a], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=d], var=[Variable: name=c], # nodes=1] +[CompositeTaskForScope: collection=[Variable: name=f], var=[Variable: name=e], # nodes=0] +[Step: name=x] +[Variable: name=a] +[Variable: name=b] +[Variable: name=c] +[Variable: name=d] +[Variable: name=e] +[Variable: name=f] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=b], var=[Variable: name=a], # nodes=1] + to: [Variable: name=a] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=d], var=[Variable: name=c], # nodes=1] + to: [Variable: name=c] +] +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=f], var=[Variable: name=e], # nodes=0] + to: [Variable: name=e] +] +[Edge + from: [Variable: name=b] + to: [CompositeTaskForScope: collection=[Variable: name=b], var=[Variable: name=a], # nodes=1] +] +[Edge + from: [Variable: name=d] + to: [CompositeTaskForScope: collection=[Variable: name=d], var=[Variable: name=c], # nodes=1] +] +[Edge + from: [Variable: name=f] + to: [CompositeTaskForScope: collection=[Variable: name=f], var=[Variable: name=e], # nodes=0] +] diff --git a/test-files/parsing/13/parsetree b/test-files/parsing/13/parsetree new file mode 100644 index 0000000..c9da633 --- /dev/null +++ b/test-files/parsing/13/parsetree @@ -0,0 +1,89 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/13/source.wdl b/test-files/parsing/13/source.wdl new file mode 100644 index 0000000..6a30bf7 --- /dev/null +++ b/test-files/parsing/13/source.wdl @@ -0,0 +1,4 @@ +composite_task foo { + for (a in b) {for (c in d) {for ( e in f) {}}} + step x[version=1000] {} +} diff --git a/test-files/parsing/13/tokens b/test-files/parsing/13/tokens new file mode 100644 index 0000000..43c9431 --- /dev/null +++ b/test-files/parsing/13/tokens @@ -0,0 +1,39 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "YQ=="}, + {"terminal": "in", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Yg=="}, + {"terminal": "rparen", "line": 2, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Yw=="}, + {"terminal": "in", "line": 2, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ZA=="}, + {"terminal": "rparen", "line": 2, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ZQ=="}, + {"terminal": "in", "line": 2, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zg=="}, + {"terminal": "rparen", "line": 2, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 2, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 2, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 2, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "eA=="}, + {"terminal": "lsquare", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "MTAwMA=="}, + {"terminal": "rsquare", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/14/ast b/test-files/parsing/14/ast new file mode 100644 index 0000000..15565dd --- /dev/null +++ b/test-files/parsing/14/ast @@ -0,0 +1,186 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ), + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ), + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ), + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ), + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=identifier, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/14/formatted b/test-files/parsing/14/formatted new file mode 100644 index 0000000..45d5263 --- /dev/null +++ b/test-files/parsing/14/formatted @@ -0,0 +1,13 @@ +composite_task MutSig { + step MutSigPreprocess[version=86] { + output: File("coverage.prepare.txt") as coverage_prepare_file, File("patients.txt") as patient_list, File("${individual_set_id}.maf") as mutation_list, File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; + } + step ProcessCoverageForMutSig[version=75] { + input: coverage=coverage_prepare_file, patients=patient_list, mutations=mutation_list; + output: File("coverage.mat") as coverage_file, File("mutcategs.txt") as category_file; + } + step MutSigRun[version=157] as MutSig { + input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file=category_file, mutation_preprocessing_report=foobar; + output: File("bargraphs.png") as graphs; + } +} diff --git a/test-files/parsing/14/graph b/test-files/parsing/14/graph new file mode 100644 index 0000000..58045d4 --- /dev/null +++ b/test-files/parsing/14/graph @@ -0,0 +1,76 @@ +VERTICIES +--------- +[Step: name=MutSigPreprocess] +[Step: name=MutSig] +[Step: name=ProcessCoverageForMutSig] +[Variable: name=category_file] +[Variable: name=coverage_file] +[Variable: name=coverage_prepare_file] +[Variable: name=foobar] +[Variable: name=graphs] +[Variable: name=mutation_list] +[Variable: name=mutation_preprocessing_report] +[Variable: name=patient_list] + +EDGES +----- +[Edge + from: [Step: name=MutSigPreprocess] + to: [Variable: name=coverage_prepare_file] +] +[Edge + from: [Step: name=MutSigPreprocess] + to: [Variable: name=mutation_list] +] +[Edge + from: [Step: name=MutSigPreprocess] + to: [Variable: name=mutation_preprocessing_report] +] +[Edge + from: [Step: name=MutSigPreprocess] + to: [Variable: name=patient_list] +] +[Edge + from: [Step: name=MutSig] + to: [Variable: name=graphs] +] +[Edge + from: [Step: name=ProcessCoverageForMutSig] + to: [Variable: name=category_file] +] +[Edge + from: [Step: name=ProcessCoverageForMutSig] + to: [Variable: name=coverage_file] +] +[Edge + from: [Variable: name=category_file] + to: [Step: name=MutSig] +] +[Edge + from: [Variable: name=coverage_file] + to: [Step: name=MutSig] +] +[Edge + from: [Variable: name=coverage_prepare_file] + to: [Step: name=ProcessCoverageForMutSig] +] +[Edge + from: [Variable: name=foobar] + to: [Step: name=MutSig] +] +[Edge + from: [Variable: name=mutation_list] + to: [Step: name=MutSig] +] +[Edge + from: [Variable: name=mutation_list] + to: [Step: name=ProcessCoverageForMutSig] +] +[Edge + from: [Variable: name=patient_list] + to: [Step: name=MutSig] +] +[Edge + from: [Variable: name=patient_list] + to: [Step: name=ProcessCoverageForMutSig] +] diff --git a/test-files/parsing/14/parsetree b/test-files/parsing/14/parsetree new file mode 100644 index 0000000..f60e872 --- /dev/null +++ b/test-files/parsing/14/parsetree @@ -0,0 +1,354 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: + comma, + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: + comma, + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: + comma, + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ) + ) + ) + ), + semi + ) + ), + (_gen3: ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: + comma, + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: + (step_name: + as, + identifier + ) + ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ) + ) + ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/14/source.wdl b/test-files/parsing/14/source.wdl new file mode 100644 index 0000000..7ae645c --- /dev/null +++ b/test-files/parsing/14/source.wdl @@ -0,0 +1,27 @@ +/* inputs: + * 1) MutSigPreprocess.{individual_set_id, maf1, maf2, maf3, maf4, maflabel1, maflabel2, maflabel3, maflabel4, wig1, wig2, wig3, wig4, build, context65_dir, build_dir, num_categories, target_list, paramfile} + * 2) ProcessCoverageForMutSig has no variables. All inputs come from prior step. + * 3) MutSigRun.{individual_set_id, gene_list, build, geneset_file, cosmic_file, refseq_file, build_dir, param_file, jobcount} + */ + +composite_task MutSig { + + step MutSigPreprocess[version=86] { + output: File("coverage.prepare.txt") as coverage_prepare_file, + File("patients.txt") as patient_list, + File("${individual_set_id}.maf") as mutation_list, + File("mutation_preprocessing_report.txt") as mutation_preprocessing_report; + } + + step ProcessCoverageForMutSig[version=75] { + input: coverage=coverage_prepare_file, patients=patient_list, mutations=mutation_list; + output: File("coverage.mat") as coverage_file, + File("mutcategs.txt") as category_file; + } + + step MutSigRun[version=157] as MutSig { + input: mutation_list=mutation_list, coverage_file=coverage_file, patients=patient_list, category_file=category_file, mutation_preprocessing_report=foobar; + output: File("bargraphs.png") as graphs; + } + +} diff --git a/test-files/parsing/14/tokens b/test-files/parsing/14/tokens new file mode 100644 index 0000000..9e30117 --- /dev/null +++ b/test-files/parsing/14/tokens @@ -0,0 +1,126 @@ +[ + {"terminal": "composite_task", "line": 7, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 7, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 9, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUHJlcHJvY2Vzcw=="}, + {"terminal": "lsquare", "line": 9, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 9, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ODY="}, + {"terminal": "rsquare", "line": 9, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 9, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLnByZXBhcmUudHh0Ig=="}, + {"terminal": "rparen", "line": 10, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, + {"terminal": "comma", "line": 10, "col": 66, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 11, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 11, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "InBhdGllbnRzLnR4dCI="}, + {"terminal": "rparen", "line": 11, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 11, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 11, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 11, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 12, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 12, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 12, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "IiR7aW5kaXZpZHVhbF9zZXRfaWR9Lm1hZiI="}, + {"terminal": "rparen", "line": 12, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 12, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 12, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "comma", "line": 12, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 13, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 13, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Im11dGF0aW9uX3ByZXByb2Nlc3NpbmdfcmVwb3J0LnR4dCI="}, + {"terminal": "rparen", "line": 13, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 13, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 13, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, + {"terminal": "semi", "line": 13, "col": 87, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 16, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "UHJvY2Vzc0NvdmVyYWdlRm9yTXV0U2ln"}, + {"terminal": "lsquare", "line": 16, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 16, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 16, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 16, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "NzU="}, + {"terminal": "rsquare", "line": 16, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 16, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 17, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 17, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 17, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2U="}, + {"terminal": "assign", "line": 17, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, + {"terminal": "comma", "line": 17, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 17, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, + {"terminal": "assign", "line": 17, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 17, "col": 65, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 17, "col": 67, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25z"}, + {"terminal": "assign", "line": 17, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 77, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "semi", "line": 17, "col": 90, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 18, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 18, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLm1hdCI="}, + {"terminal": "rparen", "line": 18, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 18, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 18, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "comma", "line": 18, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Im11dGNhdGVncy50eHQi"}, + {"terminal": "rparen", "line": 19, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 19, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 19, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "semi", "line": 19, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 20, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 22, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUnVu"}, + {"terminal": "lsquare", "line": 22, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 22, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 22, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 22, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "MTU3"}, + {"terminal": "rsquare", "line": 22, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "as", "line": 22, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 22, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, + {"terminal": "lbrace", "line": 22, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 23, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 23, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 23, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "assign", "line": 23, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "comma", "line": 23, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "assign", "line": 23, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "comma", "line": 23, "col": 68, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 70, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, + {"terminal": "assign", "line": 23, "col": 78, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 79, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 23, "col": 91, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 93, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "assign", "line": 23, "col": 106, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 107, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "comma", "line": 23, "col": 120, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 122, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, + {"terminal": "assign", "line": 23, "col": 151, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 152, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Zm9vYmFy"}, + {"terminal": "semi", "line": 23, "col": 158, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 24, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 24, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 24, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 24, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 24, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImJhcmdyYXBocy5wbmci"}, + {"terminal": "rparen", "line": 24, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 24, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 24, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Z3JhcGhz"}, + {"terminal": "semi", "line": 24, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 27, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/15/ast b/test-files/parsing/15/ast new file mode 100644 index 0000000..fd9db57 --- /dev/null +++ b/test-files/parsing/15/ast @@ -0,0 +1,4 @@ +(CompositeTask: + name=identifier, + body=[] +) \ No newline at end of file diff --git a/test-files/parsing/15/formatted b/test-files/parsing/15/formatted new file mode 100644 index 0000000..60fcec3 --- /dev/null +++ b/test-files/parsing/15/formatted @@ -0,0 +1,2 @@ +composite_task x { +} diff --git a/test-files/parsing/15/graph b/test-files/parsing/15/graph new file mode 100644 index 0000000..d612dd1 --- /dev/null +++ b/test-files/parsing/15/graph @@ -0,0 +1,5 @@ +VERTICIES +--------- + +EDGES +----- diff --git a/test-files/parsing/15/parsetree b/test-files/parsing/15/parsetree new file mode 100644 index 0000000..01245bb --- /dev/null +++ b/test-files/parsing/15/parsetree @@ -0,0 +1,14 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/15/source.wdl b/test-files/parsing/15/source.wdl new file mode 100644 index 0000000..178675b --- /dev/null +++ b/test-files/parsing/15/source.wdl @@ -0,0 +1,4 @@ +composite_task x { + /* step y[version=8989] {} */ + // step z[version=9090] {} +} diff --git a/test-files/parsing/15/tokens b/test-files/parsing/15/tokens new file mode 100644 index 0000000..c1fe161 --- /dev/null +++ b/test-files/parsing/15/tokens @@ -0,0 +1,6 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/16/ast b/test-files/parsing/16/ast new file mode 100644 index 0000000..564d566 --- /dev/null +++ b/test-files/parsing/16/ast @@ -0,0 +1,18 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=number + ) + ] + ), + name=None, + body=[] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/16/formatted b/test-files/parsing/16/formatted new file mode 100644 index 0000000..fcfa7d3 --- /dev/null +++ b/test-files/parsing/16/formatted @@ -0,0 +1,4 @@ +composite_task y { + step gamma[version=4] { + } +} diff --git a/test-files/parsing/16/graph b/test-files/parsing/16/graph new file mode 100644 index 0000000..98a171e --- /dev/null +++ b/test-files/parsing/16/graph @@ -0,0 +1,6 @@ +VERTICIES +--------- +[Step: name=gamma] + +EDGES +----- diff --git a/test-files/parsing/16/parsetree b/test-files/parsing/16/parsetree new file mode 100644 index 0000000..e6366b8 --- /dev/null +++ b/test-files/parsing/16/parsetree @@ -0,0 +1,44 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + number + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/16/source.wdl b/test-files/parsing/16/source.wdl new file mode 100644 index 0000000..fa5b09e --- /dev/null +++ b/test-files/parsing/16/source.wdl @@ -0,0 +1,11 @@ +/* +pre +*/ +composite_task /*x*/ y /*z*/ { + // step alpha {} + //step beta {} // /**/ + step gamma /* step epsilon {} */[version=/*3*/4] { /*{*/ } +} +/* +post +*/ diff --git a/test-files/parsing/16/tokens b/test-files/parsing/16/tokens new file mode 100644 index 0000000..75b7a8a --- /dev/null +++ b/test-files/parsing/16/tokens @@ -0,0 +1,15 @@ +[ + {"terminal": "composite_task", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 4, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "eQ=="}, + {"terminal": "lbrace", "line": 4, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "lsquare", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "NA=="}, + {"terminal": "rsquare", "line": 7, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 7, "col": 60, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/parsing/17/ast b/test-files/parsing/17/ast new file mode 100644 index 0000000..5a80e26 --- /dev/null +++ b/test-files/parsing/17/ast @@ -0,0 +1,94 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=string + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=string + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepFileOutput: + file=string, + var=(OutputListAppend: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/17/formatted b/test-files/parsing/17/formatted new file mode 100644 index 0000000..2f1abf4 --- /dev/null +++ b/test-files/parsing/17/formatted @@ -0,0 +1,12 @@ +composite_task x { + step a[version="1.5.6"] { + input: in0=global; + output: File("a_out.txt") as a_out; + } + for ( b in c ) { + step d[version="1.0.2"] { + input: in0=a_out, in1=b.x; + output: File("d_out.txt") as d_out; + } + } +} diff --git a/test-files/parsing/17/graph b/test-files/parsing/17/graph new file mode 100644 index 0000000..1ca6bdb --- /dev/null +++ b/test-files/parsing/17/graph @@ -0,0 +1,42 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] +[Step: name=a] +[Step: name=d] +[Variable: name=a_out] +[Variable: name=b, member=x] +[Variable: name=b] +[Variable: name=c] +[Variable: name=d_out] +[Variable: name=global] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] + to: [Variable: name=b] +] +[Edge + from: [Step: name=a] + to: [Variable: name=a_out] +] +[Edge + from: [Step: name=d] + to: [Variable: name=d_out] +] +[Edge + from: [Variable: name=a_out] + to: [Step: name=d] +] +[Edge + from: [Variable: name=b, member=x] + to: [Step: name=d] +] +[Edge + from: [Variable: name=c] + to: [CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] +] +[Edge + from: [Variable: name=global] + to: [Step: name=a] +] diff --git a/test-files/parsing/17/parsetree b/test-files/parsing/17/parsetree new file mode 100644 index 0000000..886bcd1 --- /dev/null +++ b/test-files/parsing/17/parsetree @@ -0,0 +1,195 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + string + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + string + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + file, + lparen, + string, + rparen, + (step_output_location: + into, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/17/source.wdl b/test-files/parsing/17/source.wdl new file mode 100644 index 0000000..7f3db7e --- /dev/null +++ b/test-files/parsing/17/source.wdl @@ -0,0 +1,10 @@ +composite_task x { + step a[version="1.5.6"] { + input: in0=global; output: File("a_out.txt") as a_out; + } + for ( b in c ) { + step d[version="1.0.2"] { + input: in0=a_out, in1=b.x; output: File("d_out.txt") into d_out; + } + } +} diff --git a/test-files/parsing/17/tokens b/test-files/parsing/17/tokens new file mode 100644 index 0000000..6deed3c --- /dev/null +++ b/test-files/parsing/17/tokens @@ -0,0 +1,68 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YQ=="}, + {"terminal": "lsquare", "line": 2, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 2, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "IjEuNS42Ig=="}, + {"terminal": "rsquare", "line": 2, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 3, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 3, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 3, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ImFfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 3, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "semi", "line": 3, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 5, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yg=="}, + {"terminal": "in", "line": 5, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 5, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yw=="}, + {"terminal": "rparen", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 5, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ZA=="}, + {"terminal": "lsquare", "line": 6, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 6, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 6, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 6, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "IjEuMC4yIg=="}, + {"terminal": "rsquare", "line": 6, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 6, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "comma", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4x"}, + {"terminal": "assign", "line": 7, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yg=="}, + {"terminal": "dot", "line": 7, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 7, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 7, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 7, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 7, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 7, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 7, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ImRfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 7, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 7, "col": 60, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 7, "col": 65, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ZF9vdXQ="}, + {"terminal": "semi", "line": 7, "col": 70, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 10, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="} +] diff --git a/test-files/syntax-error/4/errors b/test-files/syntax-error/4/errors new file mode 100644 index 0000000..f325fa3 --- /dev/null +++ b/test-files/syntax-error/4/errors @@ -0,0 +1,5 @@ +org.broadinstitute.parser.SyntaxError: Version information missing for task x +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/4/source.wdl @ line 3, column 8: + + step x {} + ^ diff --git a/test-files/syntax-error/4/source.wdl b/test-files/syntax-error/4/source.wdl new file mode 100644 index 0000000..b67f205 --- /dev/null +++ b/test-files/syntax-error/4/source.wdl @@ -0,0 +1,4 @@ +composite_task foo { + for (a in b) {for (c in d) {for ( e in f) {}}} + step x {} +} diff --git a/test-files/syntax-error/5/errors b/test-files/syntax-error/5/errors new file mode 100644 index 0000000..13468aa --- /dev/null +++ b/test-files/syntax-error/5/errors @@ -0,0 +1,6 @@ +org.broadinstitute.parser.SyntaxError: Unexpected symbol identifier. Expecting composite_task. +Rule: wdl := _gen0 +Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/5/source.wdl @ line 1, column 1: + +composite task foo {} +^ diff --git a/test-files/syntax-error/5/source.wdl b/test-files/syntax-error/5/source.wdl new file mode 100644 index 0000000..87fe13a --- /dev/null +++ b/test-files/syntax-error/5/source.wdl @@ -0,0 +1 @@ +composite task foo {} From 16a66af2bc09cfe2496ad76bfd15aa62ee654a41 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 13 Dec 2012 11:52:43 -0500 Subject: [PATCH 119/140] making tests more generic --- .../compositetask/CompositeTask.java | 4 + .../broadinstitute/compositetask/ParsingTest.java | 8 +- .../compositetask/SyntaxErrorTest.java | 3 +- test-files/parsing/0/tokens | 252 ++++++------- test-files/parsing/1/tokens | 282 +++++++-------- test-files/parsing/10/tokens | 24 +- test-files/parsing/11/tokens | 252 ++++++------- test-files/parsing/12/tokens | 234 ++++++------- test-files/parsing/13/tokens | 74 ++-- test-files/parsing/14/tokens | 248 ++++++------- test-files/parsing/15/tokens | 8 +- test-files/parsing/16/tokens | 26 +- test-files/parsing/17/tokens | 132 +++---- test-files/parsing/2/tokens | 390 ++++++++++----------- test-files/parsing/3/tokens | 8 +- test-files/parsing/4/tokens | 272 +++++++------- test-files/parsing/5/tokens | 288 +++++++-------- test-files/parsing/6/tokens | 316 ++++++++--------- test-files/parsing/7/tokens | 122 +++---- test-files/parsing/8/tokens | 170 ++++----- test-files/parsing/9/tokens | 26 +- test-files/syntax-error/0/errors | 2 +- test-files/syntax-error/1/errors | 2 +- test-files/syntax-error/2/errors | 2 +- test-files/syntax-error/3/errors | 2 +- test-files/syntax-error/4/errors | 2 +- test-files/syntax-error/5/errors | 2 +- 27 files changed, 1579 insertions(+), 1572 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 587068a..9686b00 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -279,6 +279,10 @@ public CompositeTask(SourceCode source_code) throws SyntaxError { this.parent = null; } + public CompositeTask(File source_code, String resource) throws SyntaxError, IOException { + this(new CompositeTaskSourceCode(source_code, resource)); + } + public CompositeTask(File source_code) throws SyntaxError, IOException { this(new CompositeTaskSourceCode(source_code)); } diff --git a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java index 8474d87..452d404 100644 --- a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java @@ -40,7 +40,8 @@ private CompositeTask getCompositeTask(File source) { try { - return new CompositeTask(source); + String relative = new File(".").toURI().relativize(source.toURI()).getPath(); + return new CompositeTask(source, relative); } catch(IOException error) { Assert.fail("IOException reading file: " + error); } catch(SyntaxError error) { @@ -57,7 +58,8 @@ public void testLexicalAnalysis(File dir) { String actual = null; try { - SourceCode code = new CompositeTaskSourceCode(source); + String relative = new File(".").toURI().relativize(source.toURI()).getPath(); + SourceCode code = new CompositeTaskSourceCode(source, relative); Lexer lexer = new Lexer(); List terminals = lexer.getTokens(code); actual = "[\n " + Utility.join(terminals, ",\n ") + "\n]\n"; @@ -79,7 +81,7 @@ public void testLexicalAnalysis(File dir) { try { String expected = Utility.readFile(tokens.getAbsolutePath()); - Assert.assertEquals(actual, expected, "Tokens list did not match"); + Assert.assertEquals(actual, expected, "Tokens list did not match."); } catch (IOException error) { Assert.fail("Cannot read " + tokens.getAbsolutePath()); } diff --git a/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java index 128b5a7..032a5ab 100644 --- a/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java +++ b/src/test/java/org/broadinstitute/compositetask/SyntaxErrorTest.java @@ -31,7 +31,8 @@ private CompositeTask getCompositeTask(File source) throws SyntaxError { try { - return new CompositeTask(source); + String relative = new File(".").toURI().relativize(source.toURI()).getPath(); + return new CompositeTask(source, relative); } catch(IOException error) { Assert.fail("IOException reading file: " + error); } diff --git a/test-files/parsing/0/tokens b/test-files/parsing/0/tokens index 308d6b4..9c59940 100644 --- a/test-files/parsing/0/tokens +++ b/test-files/parsing/0/tokens @@ -1,128 +1,128 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "R0xPQkFM"}, - {"terminal": "semi", "line": 9, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 20, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 21, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 21, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 21, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 21, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 21, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 24, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/0/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/0/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/0/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "test-files/parsing/0/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "test-files/parsing/0/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "test-files/parsing/0/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 9, "col": 18, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 22, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 29, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 9, "col": 31, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 32, "resource": "test-files/parsing/0/source.wdl", "source_string": "R0xPQkFM"}, + {"terminal": "semi", "line": 9, "col": 38, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "test-files/parsing/0/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 14, "col": 18, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 22, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 29, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 14, "col": 31, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 32, "resource": "test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 33, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 19, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 8, "resource": "test-files/parsing/0/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 21, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 22, "resource": "test-files/parsing/0/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 23, "resource": "test-files/parsing/0/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 25, "resource": "test-files/parsing/0/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 10, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 12, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 14, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 15, "resource": "test-files/parsing/0/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 20, "col": 16, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 18, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 20, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 21, "resource": "test-files/parsing/0/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 22, "resource": "test-files/parsing/0/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 24, "resource": "test-files/parsing/0/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 20, "col": 26, "resource": "test-files/parsing/0/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 27, "resource": "test-files/parsing/0/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 20, "col": 28, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 21, "col": 5, "resource": "test-files/parsing/0/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 21, "col": 11, "resource": "test-files/parsing/0/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 21, "col": 13, "resource": "test-files/parsing/0/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 21, "col": 17, "resource": "test-files/parsing/0/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 21, "col": 18, "resource": "test-files/parsing/0/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 21, "col": 30, "resource": "test-files/parsing/0/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 21, "col": 32, "resource": "test-files/parsing/0/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 21, "col": 35, "resource": "test-files/parsing/0/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 21, "col": 36, "resource": "test-files/parsing/0/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 22, "col": 3, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 24, "col": 1, "resource": "test-files/parsing/0/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/1/tokens b/test-files/parsing/1/tokens index 49b2aec..7c263c7 100644 --- a/test-files/parsing/1/tokens +++ b/test-files/parsing/1/tokens @@ -1,143 +1,143 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z2xvYmFs"}, - {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Z3Rhc2s="}, - {"terminal": "lsquare", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 25, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 25, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 25, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 26, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 26, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 26, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 26, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 27, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/1/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/1/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/1/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "test-files/parsing/1/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "test-files/parsing/1/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "test-files/parsing/1/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "test-files/parsing/1/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "test-files/parsing/1/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "test-files/parsing/1/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "test-files/parsing/1/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "test-files/parsing/1/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "test-files/parsing/1/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 24, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 22, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 23, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 25, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 25, "col": 8, "resource": "test-files/parsing/1/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 25, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 25, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 25, "col": 22, "resource": "test-files/parsing/1/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 25, "col": 23, "resource": "test-files/parsing/1/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 25, "col": 25, "resource": "test-files/parsing/1/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 26, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 26, "col": 10, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 26, "col": 12, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 26, "col": 14, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 15, "resource": "test-files/parsing/1/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 26, "col": 16, "resource": "test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 18, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 26, "col": 20, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 21, "resource": "test-files/parsing/1/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 26, "col": 22, "resource": "test-files/parsing/1/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 24, "resource": "test-files/parsing/1/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 26, "col": 26, "resource": "test-files/parsing/1/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 27, "resource": "test-files/parsing/1/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 26, "col": 28, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 27, "col": 5, "resource": "test-files/parsing/1/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 27, "col": 11, "resource": "test-files/parsing/1/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 27, "col": 13, "resource": "test-files/parsing/1/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 27, "col": 17, "resource": "test-files/parsing/1/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 27, "col": 18, "resource": "test-files/parsing/1/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 27, "col": 30, "resource": "test-files/parsing/1/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 27, "col": 32, "resource": "test-files/parsing/1/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 27, "col": 35, "resource": "test-files/parsing/1/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 27, "col": 36, "resource": "test-files/parsing/1/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 28, "col": 3, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 1, "resource": "test-files/parsing/1/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/10/tokens b/test-files/parsing/10/tokens index 800c1bc..2cc1b0b 100644 --- a/test-files/parsing/10/tokens +++ b/test-files/parsing/10/tokens @@ -1,14 +1,14 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "YQ=="}, - {"terminal": "lbrace", "line": 1, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, - {"terminal": "composite_task", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Yg=="}, - {"terminal": "lbrace", "line": 1, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, - {"terminal": "composite_task", "line": 1, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "Yw=="}, - {"terminal": "lbrace", "line": 1, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 1, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 1, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 1, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/10/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/10/source.wdl", "source_string": "YQ=="}, + {"terminal": "lbrace", "line": 1, "col": 17, "resource": "test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "composite_task", "line": 1, "col": 18, "resource": "test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 33, "resource": "test-files/parsing/10/source.wdl", "source_string": "Yg=="}, + {"terminal": "lbrace", "line": 1, "col": 34, "resource": "test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "composite_task", "line": 1, "col": 35, "resource": "test-files/parsing/10/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 50, "resource": "test-files/parsing/10/source.wdl", "source_string": "Yw=="}, + {"terminal": "lbrace", "line": 1, "col": 52, "resource": "test-files/parsing/10/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 53, "resource": "test-files/parsing/10/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 54, "resource": "test-files/parsing/10/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 55, "resource": "test-files/parsing/10/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/11/tokens b/test-files/parsing/11/tokens index 76f5064..7ad2c2b 100644 --- a/test-files/parsing/11/tokens +++ b/test-files/parsing/11/tokens @@ -1,128 +1,128 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 2, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 2, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 2, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 2, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 2, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 2, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 2, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 2, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 2, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 2, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 2, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 2, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 2, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 3, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 4, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 4, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 4, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 4, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 4, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 4, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 4, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 4, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 4, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 4, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 4, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "R0xPQkFM"}, - {"terminal": "semi", "line": 4, "col": 59, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 4, "col": 61, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 67, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 69, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 73, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 74, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 83, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 85, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 88, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 4, "col": 89, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 4, "col": 90, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 5, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 5, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 5, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 5, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 5, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 5, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 5, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 5, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 5, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 5, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 5, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 5, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 5, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 5, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 5, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 5, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 5, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 5, "col": 56, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 5, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 5, "col": 64, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 5, "col": 68, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 5, "col": 69, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 5, "col": 79, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 5, "col": 81, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 5, "col": 84, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 5, "col": 85, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 86, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 6, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 7, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 7, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 7, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 7, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 7, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 7, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 7, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 7, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 7, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 7, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 7, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 7, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 7, "col": 57, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 7, "col": 59, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 7, "col": 63, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 7, "col": 64, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 7, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 7, "col": 78, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 7, "col": 81, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 7, "col": 82, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 7, "col": 83, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 8, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/11/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/11/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/11/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 2, "col": 13, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 14, "resource": "test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 21, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 22, "resource": "test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 2, "col": 23, "resource": "test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 25, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 2, "col": 26, "resource": "test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 2, "col": 32, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 2, "col": 34, "resource": "test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 2, "col": 38, "resource": "test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 2, "col": 39, "resource": "test-files/parsing/11/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 2, "col": 48, "resource": "test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 2, "col": 50, "resource": "test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 2, "col": 53, "resource": "test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 2, "col": 54, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 2, "col": 55, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 3, "col": 3, "resource": "test-files/parsing/11/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 3, "col": 7, "resource": "test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 3, "col": 9, "resource": "test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 3, "col": 14, "resource": "test-files/parsing/11/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 3, "col": 17, "resource": "test-files/parsing/11/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 3, "col": 21, "resource": "test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 3, "col": 23, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 4, "col": 5, "resource": "test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 4, "col": 10, "resource": "test-files/parsing/11/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 4, "col": 15, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 4, "col": 16, "resource": "test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 4, "col": 23, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 4, "col": 24, "resource": "test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 4, "col": 25, "resource": "test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 4, "col": 27, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 4, "col": 28, "resource": "test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 4, "col": 33, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 4, "col": 35, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 4, "col": 37, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 38, "resource": "test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 4, "col": 39, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 41, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 4, "col": 43, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 44, "resource": "test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 4, "col": 48, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 50, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 4, "col": 52, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 53, "resource": "test-files/parsing/11/source.wdl", "source_string": "R0xPQkFM"}, + {"terminal": "semi", "line": 4, "col": 59, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 4, "col": 61, "resource": "test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 67, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 69, "resource": "test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 73, "resource": "test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 74, "resource": "test-files/parsing/11/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 83, "resource": "test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 85, "resource": "test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 88, "resource": "test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 4, "col": 89, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 90, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 5, "col": 5, "resource": "test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 5, "col": 10, "resource": "test-files/parsing/11/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 5, "col": 15, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 5, "col": 16, "resource": "test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 5, "col": 23, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 5, "col": 24, "resource": "test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 5, "col": 25, "resource": "test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 5, "col": 27, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 5, "col": 28, "resource": "test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 5, "col": 33, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 5, "col": 35, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 5, "col": 37, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 38, "resource": "test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 5, "col": 39, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 41, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 5, "col": 43, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 44, "resource": "test-files/parsing/11/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 5, "col": 48, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 50, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 5, "col": 52, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 53, "resource": "test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 5, "col": 54, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 5, "col": 56, "resource": "test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 5, "col": 62, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 5, "col": 64, "resource": "test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 5, "col": 68, "resource": "test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 5, "col": 69, "resource": "test-files/parsing/11/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 5, "col": 79, "resource": "test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 5, "col": 81, "resource": "test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 5, "col": 84, "resource": "test-files/parsing/11/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 5, "col": 85, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 86, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 6, "col": 3, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "test-files/parsing/11/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "test-files/parsing/11/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 7, "col": 13, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "test-files/parsing/11/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 21, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 22, "resource": "test-files/parsing/11/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 23, "resource": "test-files/parsing/11/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 25, "resource": "test-files/parsing/11/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 26, "resource": "test-files/parsing/11/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 31, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 33, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 7, "col": 35, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 36, "resource": "test-files/parsing/11/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 7, "col": 37, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 39, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 7, "col": 41, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 42, "resource": "test-files/parsing/11/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 7, "col": 43, "resource": "test-files/parsing/11/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 45, "resource": "test-files/parsing/11/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 7, "col": 47, "resource": "test-files/parsing/11/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 48, "resource": "test-files/parsing/11/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 7, "col": 49, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 7, "col": 51, "resource": "test-files/parsing/11/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 7, "col": 57, "resource": "test-files/parsing/11/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 7, "col": 59, "resource": "test-files/parsing/11/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 7, "col": 63, "resource": "test-files/parsing/11/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 7, "col": 64, "resource": "test-files/parsing/11/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 7, "col": 76, "resource": "test-files/parsing/11/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 7, "col": 78, "resource": "test-files/parsing/11/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 7, "col": 81, "resource": "test-files/parsing/11/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 7, "col": 82, "resource": "test-files/parsing/11/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 7, "col": 83, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 1, "resource": "test-files/parsing/11/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/12/tokens b/test-files/parsing/12/tokens index 8cb9819..cfed795 100644 --- a/test-files/parsing/12/tokens +++ b/test-files/parsing/12/tokens @@ -1,119 +1,119 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, - {"terminal": "lbrace", "line": 1, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "TGFuZUJsYWNrTGlzdA=="}, - {"terminal": "lsquare", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 2, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 2, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ng=="}, - {"terminal": "rsquare", "line": 2, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 2, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 3, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ImxhbmVfYmxhY2tsaXN0LnR4dCI="}, - {"terminal": "rparen", "line": 3, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 3, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 3, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, - {"terminal": "semi", "line": 3, "col": 57, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 5, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, - {"terminal": "in", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 5, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlcw=="}, - {"terminal": "rparen", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 5, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "UmVnaW9uQ292UGVyTGFuZQ=="}, - {"terminal": "lsquare", "line": 6, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 6, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 6, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 6, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MTY="}, - {"terminal": "rsquare", "line": 6, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 6, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, - {"terminal": "assign", "line": 7, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, - {"terminal": "dot", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 7, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFt"}, - {"terminal": "comma", "line": 7, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, - {"terminal": "assign", "line": 7, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, - {"terminal": "dot", "line": 7, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 7, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aWQ="}, - {"terminal": "semi", "line": 7, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 8, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 8, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 8, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5yY2wi"}, - {"terminal": "rparen", "line": 8, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, - {"terminal": "into", "line": 8, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, - {"terminal": "identifier", "line": 8, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNs"}, - {"terminal": "semi", "line": 8, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 9, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 10, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "TWFrZUxhbmVMaXN0"}, - {"terminal": "lsquare", "line": 10, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 10, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 10, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MTE="}, - {"terminal": "rsquare", "line": 10, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 11, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, - {"terminal": "assign", "line": 11, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, - {"terminal": "dot", "line": 11, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 11, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "YmFt"}, - {"terminal": "comma", "line": 11, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 11, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, - {"terminal": "assign", "line": 11, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 11, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, - {"terminal": "dot", "line": 11, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 11, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aWQ="}, - {"terminal": "semi", "line": 11, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 12, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 12, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 12, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 12, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5sYW5lbGlzdCI="}, - {"terminal": "rparen", "line": 12, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "KQ=="}, - {"terminal": "into", "line": 12, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, - {"terminal": "identifier", "line": 12, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, - {"terminal": "semi", "line": 12, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 15, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 15, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, - {"terminal": "lsquare", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 15, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 15, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 15, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "MjU="}, - {"terminal": "rsquare", "line": 15, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 15, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 16, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 16, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZXNfbGlzdA=="}, - {"terminal": "assign", "line": 16, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 16, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, - {"terminal": "comma", "line": 16, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 16, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNsX2xpc3Q="}, - {"terminal": "assign", "line": 16, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 16, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "cmNs"}, - {"terminal": "comma", "line": 16, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 16, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, - {"terminal": "assign", "line": 16, "col": 61, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 16, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, - {"terminal": "semi", "line": 16, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 18, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/12/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/12/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, + {"terminal": "lbrace", "line": 1, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/12/source.wdl", "source_string": "TGFuZUJsYWNrTGlzdA=="}, + {"terminal": "lsquare", "line": 2, "col": 21, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 22, "resource": "test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 30, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ng=="}, + {"terminal": "rsquare", "line": 2, "col": 31, "resource": "test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 3, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 11, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 13, "resource": "test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 17, "resource": "test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 18, "resource": "test-files/parsing/12/source.wdl", "source_string": "ImxhbmVfYmxhY2tsaXN0LnR4dCI="}, + {"terminal": "rparen", "line": 3, "col": 38, "resource": "test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 40, "resource": "test-files/parsing/12/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 43, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "semi", "line": 3, "col": 57, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 5, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 5, "col": 7, "resource": "test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 5, "col": 9, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "in", "line": 5, "col": 16, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 5, "col": 19, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlcw=="}, + {"terminal": "rparen", "line": 5, "col": 27, "resource": "test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 5, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 6, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 6, "col": 10, "resource": "test-files/parsing/12/source.wdl", "source_string": "UmVnaW9uQ292UGVyTGFuZQ=="}, + {"terminal": "lsquare", "line": 6, "col": 26, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 6, "col": 27, "resource": "test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 6, "col": 34, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 6, "col": 35, "resource": "test-files/parsing/12/source.wdl", "source_string": "MTY="}, + {"terminal": "rsquare", "line": 6, "col": 37, "resource": "test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 6, "col": 39, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 7, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 12, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, + {"terminal": "assign", "line": 7, "col": 22, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 23, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 7, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 30, "resource": "test-files/parsing/12/source.wdl", "source_string": "YmFt"}, + {"terminal": "comma", "line": 7, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 35, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, + {"terminal": "assign", "line": 7, "col": 44, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 45, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 7, "col": 51, "resource": "test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 52, "resource": "test-files/parsing/12/source.wdl", "source_string": "aWQ="}, + {"terminal": "semi", "line": 7, "col": 54, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 8, "col": 7, "resource": "test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 13, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 15, "resource": "test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 19, "resource": "test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 20, "resource": "test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5yY2wi"}, + {"terminal": "rparen", "line": 8, "col": 38, "resource": "test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 8, "col": 40, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 8, "col": 45, "resource": "test-files/parsing/12/source.wdl", "source_string": "cmNs"}, + {"terminal": "semi", "line": 8, "col": 48, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 10, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 10, "col": 10, "resource": "test-files/parsing/12/source.wdl", "source_string": "TWFrZUxhbmVMaXN0"}, + {"terminal": "lsquare", "line": 10, "col": 22, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 10, "col": 23, "resource": "test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 10, "col": 30, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 10, "col": 31, "resource": "test-files/parsing/12/source.wdl", "source_string": "MTE="}, + {"terminal": "rsquare", "line": 10, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 10, "col": 35, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 11, "col": 7, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 11, "col": 12, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 11, "col": 14, "resource": "test-files/parsing/12/source.wdl", "source_string": "YmFtX2ZpbGU="}, + {"terminal": "assign", "line": 11, "col": 22, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 11, "col": 23, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 11, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 11, "col": 30, "resource": "test-files/parsing/12/source.wdl", "source_string": "YmFt"}, + {"terminal": "comma", "line": 11, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 11, "col": 35, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxlX2lk"}, + {"terminal": "assign", "line": 11, "col": 44, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 11, "col": 45, "resource": "test-files/parsing/12/source.wdl", "source_string": "c2FtcGxl"}, + {"terminal": "dot", "line": 11, "col": 51, "resource": "test-files/parsing/12/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 11, "col": 52, "resource": "test-files/parsing/12/source.wdl", "source_string": "aWQ="}, + {"terminal": "semi", "line": 11, "col": 54, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 12, "col": 7, "resource": "test-files/parsing/12/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 12, "col": 13, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 12, "col": 15, "resource": "test-files/parsing/12/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 12, "col": 19, "resource": "test-files/parsing/12/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 12, "col": 20, "resource": "test-files/parsing/12/source.wdl", "source_string": "IiR7c2FtcGxlLmlkfS5sYW5lbGlzdCI="}, + {"terminal": "rparen", "line": 12, "col": 43, "resource": "test-files/parsing/12/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 12, "col": 45, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 12, "col": 50, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, + {"terminal": "semi", "line": 12, "col": 58, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 13, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 14, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 15, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 15, "col": 8, "resource": "test-files/parsing/12/source.wdl", "source_string": "Q29weU51bWJlclFD"}, + {"terminal": "lsquare", "line": 15, "col": 20, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 15, "col": 21, "resource": "test-files/parsing/12/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 15, "col": 28, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 15, "col": 29, "resource": "test-files/parsing/12/source.wdl", "source_string": "MjU="}, + {"terminal": "rsquare", "line": 15, "col": 31, "resource": "test-files/parsing/12/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 15, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 16, "col": 5, "resource": "test-files/parsing/12/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 16, "col": 10, "resource": "test-files/parsing/12/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 16, "col": 12, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZXNfbGlzdA=="}, + {"terminal": "assign", "line": 16, "col": 22, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 23, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZWxpc3Q="}, + {"terminal": "comma", "line": 16, "col": 31, "resource": "test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 16, "col": 33, "resource": "test-files/parsing/12/source.wdl", "source_string": "cmNsX2xpc3Q="}, + {"terminal": "assign", "line": 16, "col": 41, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 42, "resource": "test-files/parsing/12/source.wdl", "source_string": "cmNs"}, + {"terminal": "comma", "line": 16, "col": 45, "resource": "test-files/parsing/12/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 16, "col": 47, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "assign", "line": 16, "col": 61, "resource": "test-files/parsing/12/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 62, "resource": "test-files/parsing/12/source.wdl", "source_string": "bGFuZV9ibGFja2xpc3Q="}, + {"terminal": "semi", "line": 16, "col": 76, "resource": "test-files/parsing/12/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 18, "col": 1, "resource": "test-files/parsing/12/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/13/tokens b/test-files/parsing/13/tokens index 43c9431..64adcdd 100644 --- a/test-files/parsing/13/tokens +++ b/test-files/parsing/13/tokens @@ -1,39 +1,39 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 2, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "YQ=="}, - {"terminal": "in", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Yg=="}, - {"terminal": "rparen", "line": 2, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 2, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 2, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 2, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Yw=="}, - {"terminal": "in", "line": 2, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 2, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ZA=="}, - {"terminal": "rparen", "line": 2, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 2, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 2, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 2, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 2, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ZQ=="}, - {"terminal": "in", "line": 2, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 2, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Zg=="}, - {"terminal": "rparen", "line": 2, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 2, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 2, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 2, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 2, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "eA=="}, - {"terminal": "lsquare", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "MTAwMA=="}, - {"terminal": "rsquare", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/13/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/13/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/13/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 3, "resource": "test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 7, "resource": "test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/13/source.wdl", "source_string": "YQ=="}, + {"terminal": "in", "line": 2, "col": 10, "resource": "test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 13, "resource": "test-files/parsing/13/source.wdl", "source_string": "Yg=="}, + {"terminal": "rparen", "line": 2, "col": 14, "resource": "test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 16, "resource": "test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 17, "resource": "test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 21, "resource": "test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 22, "resource": "test-files/parsing/13/source.wdl", "source_string": "Yw=="}, + {"terminal": "in", "line": 2, "col": 24, "resource": "test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 27, "resource": "test-files/parsing/13/source.wdl", "source_string": "ZA=="}, + {"terminal": "rparen", "line": 2, "col": 28, "resource": "test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 30, "resource": "test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 31, "resource": "test-files/parsing/13/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 35, "resource": "test-files/parsing/13/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 37, "resource": "test-files/parsing/13/source.wdl", "source_string": "ZQ=="}, + {"terminal": "in", "line": 2, "col": 39, "resource": "test-files/parsing/13/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 42, "resource": "test-files/parsing/13/source.wdl", "source_string": "Zg=="}, + {"terminal": "rparen", "line": 2, "col": 43, "resource": "test-files/parsing/13/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 45, "resource": "test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 2, "col": 46, "resource": "test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 2, "col": 47, "resource": "test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 2, "col": 48, "resource": "test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/13/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/13/source.wdl", "source_string": "eA=="}, + {"terminal": "lsquare", "line": 3, "col": 9, "resource": "test-files/parsing/13/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 10, "resource": "test-files/parsing/13/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 17, "resource": "test-files/parsing/13/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 18, "resource": "test-files/parsing/13/source.wdl", "source_string": "MTAwMA=="}, + {"terminal": "rsquare", "line": 3, "col": 22, "resource": "test-files/parsing/13/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 24, "resource": "test-files/parsing/13/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 3, "col": 25, "resource": "test-files/parsing/13/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 4, "col": 1, "resource": "test-files/parsing/13/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/14/tokens b/test-files/parsing/14/tokens index 9e30117..6484c7f 100644 --- a/test-files/parsing/14/tokens +++ b/test-files/parsing/14/tokens @@ -1,126 +1,126 @@ [ - {"terminal": "composite_task", "line": 7, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 7, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 9, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUHJlcHJvY2Vzcw=="}, - {"terminal": "lsquare", "line": 9, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 9, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ODY="}, - {"terminal": "rsquare", "line": 9, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 9, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLnByZXBhcmUudHh0Ig=="}, - {"terminal": "rparen", "line": 10, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, - {"terminal": "comma", "line": 10, "col": 66, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "file", "line": 11, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 11, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "InBhdGllbnRzLnR4dCI="}, - {"terminal": "rparen", "line": 11, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 11, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 11, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, - {"terminal": "comma", "line": 11, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "file", "line": 12, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 12, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 12, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "IiR7aW5kaXZpZHVhbF9zZXRfaWR9Lm1hZiI="}, - {"terminal": "rparen", "line": 12, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 12, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 12, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, - {"terminal": "comma", "line": 12, "col": 62, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "file", "line": 13, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 13, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Im11dGF0aW9uX3ByZXByb2Nlc3NpbmdfcmVwb3J0LnR4dCI="}, - {"terminal": "rparen", "line": 13, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 13, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 13, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, - {"terminal": "semi", "line": 13, "col": 87, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 16, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "UHJvY2Vzc0NvdmVyYWdlRm9yTXV0U2ln"}, - {"terminal": "lsquare", "line": 16, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 16, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 16, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 16, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "NzU="}, - {"terminal": "rsquare", "line": 16, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 16, "col": 45, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 17, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 17, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 17, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2U="}, - {"terminal": "assign", "line": 17, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 17, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, - {"terminal": "comma", "line": 17, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 17, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, - {"terminal": "assign", "line": 17, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 17, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, - {"terminal": "comma", "line": 17, "col": 65, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 17, "col": 67, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25z"}, - {"terminal": "assign", "line": 17, "col": 76, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 17, "col": 77, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, - {"terminal": "semi", "line": 17, "col": 90, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 18, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 18, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLm1hdCI="}, - {"terminal": "rparen", "line": 18, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 18, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 18, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, - {"terminal": "comma", "line": 18, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "file", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Im11dGNhdGVncy50eHQi"}, - {"terminal": "rparen", "line": 19, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 19, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 19, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, - {"terminal": "semi", "line": 19, "col": 51, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 20, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 22, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 22, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUnVu"}, - {"terminal": "lsquare", "line": 22, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 22, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 22, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 22, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "MTU3"}, - {"terminal": "rsquare", "line": 22, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "XQ=="}, - {"terminal": "as", "line": 22, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 22, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, - {"terminal": "lbrace", "line": 22, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 23, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 23, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 23, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, - {"terminal": "assign", "line": 23, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 23, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, - {"terminal": "comma", "line": 23, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 23, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, - {"terminal": "assign", "line": 23, "col": 54, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 23, "col": 55, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, - {"terminal": "comma", "line": 23, "col": 68, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 23, "col": 70, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, - {"terminal": "assign", "line": 23, "col": 78, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 23, "col": 79, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, - {"terminal": "comma", "line": 23, "col": 91, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 23, "col": 93, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, - {"terminal": "assign", "line": 23, "col": 106, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 23, "col": 107, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, - {"terminal": "comma", "line": 23, "col": 120, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 23, "col": 122, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, - {"terminal": "assign", "line": 23, "col": 151, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 23, "col": 152, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Zm9vYmFy"}, - {"terminal": "semi", "line": 23, "col": 158, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 24, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 24, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 24, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 24, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 24, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "ImJhcmdyYXBocy5wbmci"}, - {"terminal": "rparen", "line": 24, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 24, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 24, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Z3JhcGhz"}, - {"terminal": "semi", "line": 24, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 27, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/14/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 7, "col": 1, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 7, "col": 16, "resource": "test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 9, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 9, "col": 8, "resource": "test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUHJlcHJvY2Vzcw=="}, + {"terminal": "lsquare", "line": 9, "col": 24, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 9, "col": 25, "resource": "test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 9, "col": 32, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 9, "col": 33, "resource": "test-files/parsing/14/source.wdl", "source_string": "ODY="}, + {"terminal": "rsquare", "line": 9, "col": 35, "resource": "test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 9, "col": 37, "resource": "test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 10, "col": 5, "resource": "test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 11, "resource": "test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLnByZXBhcmUudHh0Ig=="}, + {"terminal": "rparen", "line": 10, "col": 40, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 42, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 45, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, + {"terminal": "comma", "line": 10, "col": 66, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 11, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 11, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 11, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "InBhdGllbnRzLnR4dCI="}, + {"terminal": "rparen", "line": 11, "col": 32, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 11, "col": 34, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 11, "col": 37, "resource": "test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 11, "col": 49, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 12, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 12, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 12, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "IiR7aW5kaXZpZHVhbF9zZXRfaWR9Lm1hZiI="}, + {"terminal": "rparen", "line": 12, "col": 44, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 12, "col": 46, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 12, "col": 49, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "comma", "line": 12, "col": 62, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 13, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 13, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 13, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "Im11dGF0aW9uX3ByZXByb2Nlc3NpbmdfcmVwb3J0LnR4dCI="}, + {"terminal": "rparen", "line": 13, "col": 53, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 13, "col": 55, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 13, "col": 58, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, + {"terminal": "semi", "line": 13, "col": 87, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 14, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 16, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 16, "col": 8, "resource": "test-files/parsing/14/source.wdl", "source_string": "UHJvY2Vzc0NvdmVyYWdlRm9yTXV0U2ln"}, + {"terminal": "lsquare", "line": 16, "col": 32, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 16, "col": 33, "resource": "test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 16, "col": 40, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 16, "col": 41, "resource": "test-files/parsing/14/source.wdl", "source_string": "NzU="}, + {"terminal": "rsquare", "line": 16, "col": 43, "resource": "test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 16, "col": 45, "resource": "test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 17, "col": 5, "resource": "test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 17, "col": 10, "resource": "test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 17, "col": 12, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2U="}, + {"terminal": "assign", "line": 17, "col": 20, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 21, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfcHJlcGFyZV9maWxl"}, + {"terminal": "comma", "line": 17, "col": 42, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 17, "col": 44, "resource": "test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, + {"terminal": "assign", "line": 17, "col": 52, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 53, "resource": "test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 17, "col": 65, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 17, "col": 67, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25z"}, + {"terminal": "assign", "line": 17, "col": 76, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 17, "col": 77, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "semi", "line": 17, "col": 90, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 18, "col": 5, "resource": "test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 18, "col": 11, "resource": "test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 18, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 18, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 18, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "ImNvdmVyYWdlLm1hdCI="}, + {"terminal": "rparen", "line": 18, "col": 32, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 18, "col": 34, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 18, "col": 37, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "comma", "line": 18, "col": 50, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "file", "line": 19, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 19, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 19, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "Im11dGNhdGVncy50eHQi"}, + {"terminal": "rparen", "line": 19, "col": 33, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 19, "col": 35, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 19, "col": 38, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "semi", "line": 19, "col": 51, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 20, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 22, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 22, "col": 8, "resource": "test-files/parsing/14/source.wdl", "source_string": "TXV0U2lnUnVu"}, + {"terminal": "lsquare", "line": 22, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 22, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 22, "col": 25, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 22, "col": 26, "resource": "test-files/parsing/14/source.wdl", "source_string": "MTU3"}, + {"terminal": "rsquare", "line": 22, "col": 29, "resource": "test-files/parsing/14/source.wdl", "source_string": "XQ=="}, + {"terminal": "as", "line": 22, "col": 31, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 22, "col": 34, "resource": "test-files/parsing/14/source.wdl", "source_string": "TXV0U2ln"}, + {"terminal": "lbrace", "line": 22, "col": 41, "resource": "test-files/parsing/14/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 23, "col": 5, "resource": "test-files/parsing/14/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 23, "col": 10, "resource": "test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 23, "col": 12, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "assign", "line": 23, "col": 25, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 26, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fbGlzdA=="}, + {"terminal": "comma", "line": 23, "col": 39, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 41, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "assign", "line": 23, "col": 54, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 55, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y292ZXJhZ2VfZmlsZQ=="}, + {"terminal": "comma", "line": 23, "col": 68, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 70, "resource": "test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudHM="}, + {"terminal": "assign", "line": 23, "col": 78, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 79, "resource": "test-files/parsing/14/source.wdl", "source_string": "cGF0aWVudF9saXN0"}, + {"terminal": "comma", "line": 23, "col": 91, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 93, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "assign", "line": 23, "col": 106, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 107, "resource": "test-files/parsing/14/source.wdl", "source_string": "Y2F0ZWdvcnlfZmlsZQ=="}, + {"terminal": "comma", "line": 23, "col": 120, "resource": "test-files/parsing/14/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 23, "col": 122, "resource": "test-files/parsing/14/source.wdl", "source_string": "bXV0YXRpb25fcHJlcHJvY2Vzc2luZ19yZXBvcnQ="}, + {"terminal": "assign", "line": 23, "col": 151, "resource": "test-files/parsing/14/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 23, "col": 152, "resource": "test-files/parsing/14/source.wdl", "source_string": "Zm9vYmFy"}, + {"terminal": "semi", "line": 23, "col": 158, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 24, "col": 5, "resource": "test-files/parsing/14/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 24, "col": 11, "resource": "test-files/parsing/14/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 24, "col": 13, "resource": "test-files/parsing/14/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 24, "col": 17, "resource": "test-files/parsing/14/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 24, "col": 18, "resource": "test-files/parsing/14/source.wdl", "source_string": "ImJhcmdyYXBocy5wbmci"}, + {"terminal": "rparen", "line": 24, "col": 33, "resource": "test-files/parsing/14/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 24, "col": 35, "resource": "test-files/parsing/14/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 24, "col": 38, "resource": "test-files/parsing/14/source.wdl", "source_string": "Z3JhcGhz"}, + {"terminal": "semi", "line": 24, "col": 44, "resource": "test-files/parsing/14/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 25, "col": 3, "resource": "test-files/parsing/14/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 27, "col": 1, "resource": "test-files/parsing/14/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/15/tokens b/test-files/parsing/15/tokens index c1fe161..a1d1a66 100644 --- a/test-files/parsing/15/tokens +++ b/test-files/parsing/15/tokens @@ -1,6 +1,6 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "eA=="}, - {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/15/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/15/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/15/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "test-files/parsing/15/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 4, "col": 1, "resource": "test-files/parsing/15/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/16/tokens b/test-files/parsing/16/tokens index 75b7a8a..9b880f9 100644 --- a/test-files/parsing/16/tokens +++ b/test-files/parsing/16/tokens @@ -1,15 +1,15 @@ [ - {"terminal": "composite_task", "line": 4, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 4, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "eQ=="}, - {"terminal": "lbrace", "line": 4, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "lsquare", "line": 7, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 7, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 7, "col": 43, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 7, "col": 49, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "NA=="}, - {"terminal": "rsquare", "line": 7, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 7, "col": 52, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 7, "col": 60, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 8, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/16/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 4, "col": 1, "resource": "test-files/parsing/16/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 4, "col": 22, "resource": "test-files/parsing/16/source.wdl", "source_string": "eQ=="}, + {"terminal": "lbrace", "line": 4, "col": 30, "resource": "test-files/parsing/16/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "test-files/parsing/16/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "test-files/parsing/16/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "lsquare", "line": 7, "col": 35, "resource": "test-files/parsing/16/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 36, "resource": "test-files/parsing/16/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 43, "resource": "test-files/parsing/16/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 49, "resource": "test-files/parsing/16/source.wdl", "source_string": "NA=="}, + {"terminal": "rsquare", "line": 7, "col": 50, "resource": "test-files/parsing/16/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 52, "resource": "test-files/parsing/16/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 7, "col": 60, "resource": "test-files/parsing/16/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 1, "resource": "test-files/parsing/16/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/17/tokens b/test-files/parsing/17/tokens index 6deed3c..6d39aaa 100644 --- a/test-files/parsing/17/tokens +++ b/test-files/parsing/17/tokens @@ -1,68 +1,68 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "eA=="}, - {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YQ=="}, - {"terminal": "lsquare", "line": 2, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 2, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, - {"terminal": "string", "line": 2, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "IjEuNS42Ig=="}, - {"terminal": "rsquare", "line": 2, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 2, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 3, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4w"}, - {"terminal": "assign", "line": 3, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 3, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Z2xvYmFs"}, - {"terminal": "semi", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 3, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 3, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 3, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ImFfb3V0LnR4dCI="}, - {"terminal": "rparen", "line": 3, "col": 48, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 3, "col": 50, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 3, "col": 53, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, - {"terminal": "semi", "line": 3, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 5, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yg=="}, - {"terminal": "in", "line": 5, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 5, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yw=="}, - {"terminal": "rparen", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 5, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ZA=="}, - {"terminal": "lsquare", "line": 6, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 6, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 6, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, - {"terminal": "string", "line": 6, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "IjEuMC4yIg=="}, - {"terminal": "rsquare", "line": 6, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 6, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4w"}, - {"terminal": "assign", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, - {"terminal": "comma", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW4x"}, - {"terminal": "assign", "line": 7, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Yg=="}, - {"terminal": "dot", "line": 7, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 7, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 7, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 7, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 7, "col": 40, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 7, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 7, "col": 46, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 7, "col": 47, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ImRfb3V0LnR4dCI="}, - {"terminal": "rparen", "line": 7, "col": 58, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "KQ=="}, - {"terminal": "into", "line": 7, "col": 60, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "aW50bw=="}, - {"terminal": "identifier", "line": 7, "col": 65, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "ZF9vdXQ="}, - {"terminal": "semi", "line": 7, "col": 70, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 10, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/17/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/17/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/17/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/17/source.wdl", "source_string": "YQ=="}, + {"terminal": "lsquare", "line": 2, "col": 9, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 10, "resource": "test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 17, "resource": "test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 2, "col": 18, "resource": "test-files/parsing/17/source.wdl", "source_string": "IjEuNS42Ig=="}, + {"terminal": "rsquare", "line": 2, "col": 25, "resource": "test-files/parsing/17/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 27, "resource": "test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 3, "col": 5, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 3, "col": 10, "resource": "test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 3, "col": 12, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 3, "col": 15, "resource": "test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 3, "col": 16, "resource": "test-files/parsing/17/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 3, "col": 22, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 3, "col": 24, "resource": "test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 30, "resource": "test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 32, "resource": "test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 36, "resource": "test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 37, "resource": "test-files/parsing/17/source.wdl", "source_string": "ImFfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 3, "col": 48, "resource": "test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 50, "resource": "test-files/parsing/17/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 53, "resource": "test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "semi", "line": 3, "col": 58, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 5, "col": 3, "resource": "test-files/parsing/17/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 5, "col": 7, "resource": "test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 5, "col": 9, "resource": "test-files/parsing/17/source.wdl", "source_string": "Yg=="}, + {"terminal": "in", "line": 5, "col": 11, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 5, "col": 14, "resource": "test-files/parsing/17/source.wdl", "source_string": "Yw=="}, + {"terminal": "rparen", "line": 5, "col": 16, "resource": "test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 5, "col": 18, "resource": "test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 6, "col": 5, "resource": "test-files/parsing/17/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 6, "col": 10, "resource": "test-files/parsing/17/source.wdl", "source_string": "ZA=="}, + {"terminal": "lsquare", "line": 6, "col": 11, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 6, "col": 12, "resource": "test-files/parsing/17/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 6, "col": 19, "resource": "test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 6, "col": 20, "resource": "test-files/parsing/17/source.wdl", "source_string": "IjEuMC4yIg=="}, + {"terminal": "rsquare", "line": 6, "col": 27, "resource": "test-files/parsing/17/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 6, "col": 29, "resource": "test-files/parsing/17/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 7, "col": 7, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 7, "col": 12, "resource": "test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 7, "col": 14, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 7, "col": 17, "resource": "test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "test-files/parsing/17/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "comma", "line": 7, "col": 23, "resource": "test-files/parsing/17/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 7, "col": 25, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW4x"}, + {"terminal": "assign", "line": 7, "col": 28, "resource": "test-files/parsing/17/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 7, "col": 29, "resource": "test-files/parsing/17/source.wdl", "source_string": "Yg=="}, + {"terminal": "dot", "line": 7, "col": 30, "resource": "test-files/parsing/17/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 7, "col": 31, "resource": "test-files/parsing/17/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 7, "col": 32, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 7, "col": 34, "resource": "test-files/parsing/17/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 7, "col": 40, "resource": "test-files/parsing/17/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 7, "col": 42, "resource": "test-files/parsing/17/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 7, "col": 46, "resource": "test-files/parsing/17/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 7, "col": 47, "resource": "test-files/parsing/17/source.wdl", "source_string": "ImRfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 7, "col": 58, "resource": "test-files/parsing/17/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 7, "col": 60, "resource": "test-files/parsing/17/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 7, "col": 65, "resource": "test-files/parsing/17/source.wdl", "source_string": "ZF9vdXQ="}, + {"terminal": "semi", "line": 7, "col": 70, "resource": "test-files/parsing/17/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 8, "col": 5, "resource": "test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "test-files/parsing/17/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 10, "col": 1, "resource": "test-files/parsing/17/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/2/tokens b/test-files/parsing/2/tokens index 58b8ba8..7dfb38c 100644 --- a/test-files/parsing/2/tokens +++ b/test-files/parsing/2/tokens @@ -1,197 +1,197 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 7, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, - {"terminal": "rparen", "line": 7, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFs"}, - {"terminal": "semi", "line": 9, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 13, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 13, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y3Rhc2s="}, - {"terminal": "lsquare", "line": 13, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 13, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 13, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 14, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 14, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 14, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "comma", "line": 14, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 14, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 15, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 15, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 18, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 18, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "in", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 18, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "rparen", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZHRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 20, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 20, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "composite_task", "line": 23, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 23, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Zm9vX3N1Yg=="}, - {"terminal": "lbrace", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 24, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZXRhc2s="}, - {"terminal": "lsquare", "line": 24, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 24, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 24, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 24, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 24, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 25, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 25, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, - {"terminal": "comma", "line": 25, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 25, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 25, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 25, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 25, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 25, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 27, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 27, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ZnRhc2s="}, - {"terminal": "lsquare", "line": 27, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 27, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 27, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 27, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 27, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 28, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 28, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 28, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, - {"terminal": "comma", "line": 28, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 28, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "comma", "line": 28, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 28, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 28, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 28, "col": 44, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 29, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 30, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 31, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 32, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 34, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 34, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Z3Rhc2s="}, - {"terminal": "lsquare", "line": 34, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 34, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 34, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 34, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 34, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 34, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 35, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 35, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 35, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 35, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 35, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 35, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 35, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 35, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 35, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 35, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 35, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 35, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 36, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 36, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 36, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 36, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 36, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 36, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 36, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 36, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "cg=="}, - {"terminal": "semi", "line": 36, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 37, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 39, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/2/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/2/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 3, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 22, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 4, "col": 33, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 7, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 7, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "Zm9v"}, + {"terminal": "rparen", "line": 7, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 10, "resource": "test-files/parsing/2/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 8, "col": 15, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 24, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 12, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 9, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 26, "resource": "test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 9, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 15, "resource": "test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 19, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 10, "col": 29, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 31, "resource": "test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 34, "resource": "test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 13, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 13, "col": 10, "resource": "test-files/parsing/2/source.wdl", "source_string": "Y3Rhc2s="}, + {"terminal": "lsquare", "line": 13, "col": 15, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 13, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 13, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 13, "col": 24, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 13, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 13, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 14, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 14, "col": 12, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 14, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 14, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "comma", "line": 14, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 14, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 14, "col": 26, "resource": "test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 14, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 15, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 15, "resource": "test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 19, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 15, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 35, "resource": "test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 11, "resource": "test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "in", "line": 18, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "rparen", "line": 18, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 12, "resource": "test-files/parsing/2/source.wdl", "source_string": "ZHRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 26, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 29, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 19, "resource": "test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 20, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 22, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 20, "col": 24, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 20, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 21, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "composite_task", "line": 23, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 23, "col": 22, "resource": "test-files/parsing/2/source.wdl", "source_string": "Zm9vX3N1Yg=="}, + {"terminal": "lbrace", "line": 23, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 24, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 24, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "ZXRhc2s="}, + {"terminal": "lsquare", "line": 24, "col": 19, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 24, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 24, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 24, "col": 28, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 24, "col": 29, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 24, "col": 31, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 25, "col": 11, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 25, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 25, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 25, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 25, "col": 28, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 25, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 33, "resource": "test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 25, "col": 34, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 25, "col": 36, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 25, "col": 38, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 25, "col": 39, "resource": "test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 25, "col": 44, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 26, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 27, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 27, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "ZnRhc2s="}, + {"terminal": "lsquare", "line": 27, "col": 19, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 27, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 27, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 27, "col": 28, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 27, "col": 29, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 27, "col": 31, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 28, "col": 11, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 28, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 28, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 28, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "Z2xvYmFsMQ=="}, + {"terminal": "comma", "line": 28, "col": 28, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 28, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 33, "resource": "test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "comma", "line": 28, "col": 34, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 36, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 28, "col": 38, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 39, "resource": "test-files/parsing/2/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 28, "col": 44, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 29, "col": 9, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 7, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 31, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 32, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 34, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 34, "col": 8, "resource": "test-files/parsing/2/source.wdl", "source_string": "Z3Rhc2s="}, + {"terminal": "lsquare", "line": 34, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 34, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 34, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 34, "col": 22, "resource": "test-files/parsing/2/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 34, "col": 23, "resource": "test-files/parsing/2/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 34, "col": 25, "resource": "test-files/parsing/2/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 35, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 35, "col": 10, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 35, "col": 12, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 35, "col": 14, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 15, "resource": "test-files/parsing/2/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 35, "col": 16, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 35, "col": 20, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 21, "resource": "test-files/parsing/2/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 35, "col": 22, "resource": "test-files/parsing/2/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 35, "col": 24, "resource": "test-files/parsing/2/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 35, "col": 26, "resource": "test-files/parsing/2/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 35, "col": 27, "resource": "test-files/parsing/2/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 35, "col": 28, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 36, "col": 5, "resource": "test-files/parsing/2/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 36, "col": 11, "resource": "test-files/parsing/2/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 36, "col": 13, "resource": "test-files/parsing/2/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 36, "col": 17, "resource": "test-files/parsing/2/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 36, "col": 18, "resource": "test-files/parsing/2/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 36, "col": 30, "resource": "test-files/parsing/2/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 36, "col": 32, "resource": "test-files/parsing/2/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 36, "col": 35, "resource": "test-files/parsing/2/source.wdl", "source_string": "cg=="}, + {"terminal": "semi", "line": 36, "col": 36, "resource": "test-files/parsing/2/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 37, "col": 3, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 39, "col": 1, "resource": "test-files/parsing/2/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/3/tokens b/test-files/parsing/3/tokens index 209f814..b05c651 100644 --- a/test-files/parsing/3/tokens +++ b/test-files/parsing/3/tokens @@ -1,6 +1,6 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/3/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/3/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/3/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/3/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 21, "resource": "test-files/parsing/3/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/4/tokens b/test-files/parsing/4/tokens index 4491806..1bdc6e3 100644 --- a/test-files/parsing/4/tokens +++ b/test-files/parsing/4/tokens @@ -1,138 +1,138 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, - {"terminal": "lsquare", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "bG9uZ190YXNr"}, - {"terminal": "lsquare", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 7, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 8, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 8, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 8, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 8, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 8, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "semi", "line": 8, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 11, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbXM="}, - {"terminal": "rparen", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 11, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 12, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 12, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 12, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 12, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 12, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 12, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 13, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 13, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 13, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "comma", "line": 13, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 13, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "dot", "line": 13, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 13, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 13, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 14, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 14, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 14, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ImJhei50eHQi"}, - {"terminal": "rparen", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 14, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "semi", "line": 14, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 17, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 17, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 17, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 17, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 17, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 17, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 17, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 17, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 18, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 18, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 18, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "comma", "line": 18, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 18, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "dot", "line": 18, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 18, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 18, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 19, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 19, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 19, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 19, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 19, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 19, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 19, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 19, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 20, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 21, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 23, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, - {"terminal": "lsquare", "line": 23, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 23, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 23, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 23, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 23, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 23, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 24, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 24, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 24, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 24, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 24, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "comma", "line": 24, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 24, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 24, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 24, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 24, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 25, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 25, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 25, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 25, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 25, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 25, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 25, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "cmVwb3J0"}, - {"terminal": "semi", "line": 25, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 26, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 28, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/4/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/4/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/4/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/4/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 18, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 19, "resource": "test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 26, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 28, "resource": "test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 30, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "test-files/parsing/4/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 4, "col": 37, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "test-files/parsing/4/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 7, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 26, "resource": "test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 29, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 8, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 11, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 13, "resource": "test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 18, "resource": "test-files/parsing/4/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 8, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 8, "col": 29, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 8, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 8, "col": 36, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 11, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 11, "col": 7, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 11, "col": 9, "resource": "test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 11, "col": 14, "resource": "test-files/parsing/4/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 11, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 11, "col": 23, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 11, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 12, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 12, "col": 10, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 12, "col": 15, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 12, "col": 16, "resource": "test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 12, "col": 23, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 12, "col": 24, "resource": "test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 12, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 12, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 13, "col": 7, "resource": "test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 13, "col": 12, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 13, "col": 14, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 13, "col": 16, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 13, "col": 22, "resource": "test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 13, "col": 24, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 13, "col": 26, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 13, "col": 31, "resource": "test-files/parsing/4/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 13, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 13, "col": 33, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 14, "col": 7, "resource": "test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 14, "col": 13, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 14, "col": 15, "resource": "test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 14, "col": 19, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 14, "col": 20, "resource": "test-files/parsing/4/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 14, "col": 29, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 14, "col": 31, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 14, "col": 34, "resource": "test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 14, "col": 39, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 15, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 17, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 17, "col": 10, "resource": "test-files/parsing/4/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 17, "col": 15, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 17, "col": 16, "resource": "test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 17, "col": 23, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 17, "col": 24, "resource": "test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 17, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 17, "col": 27, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 18, "col": 7, "resource": "test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 18, "col": 12, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 18, "col": 14, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 18, "col": 16, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 18, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 18, "col": 21, "resource": "test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 18, "col": 23, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 18, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 18, "col": 26, "resource": "test-files/parsing/4/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 18, "col": 30, "resource": "test-files/parsing/4/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 18, "col": 31, "resource": "test-files/parsing/4/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 18, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 19, "col": 7, "resource": "test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 19, "col": 13, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 19, "col": 15, "resource": "test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 19, "col": 19, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 19, "col": 20, "resource": "test-files/parsing/4/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 19, "col": 30, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 19, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 19, "col": 35, "resource": "test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 19, "col": 42, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 20, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 21, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 23, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 23, "col": 8, "resource": "test-files/parsing/4/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 23, "col": 23, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 23, "col": 24, "resource": "test-files/parsing/4/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 23, "col": 31, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 23, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 23, "col": 33, "resource": "test-files/parsing/4/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 23, "col": 35, "resource": "test-files/parsing/4/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 24, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 24, "col": 10, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 24, "col": 12, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 24, "col": 14, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 24, "col": 15, "resource": "test-files/parsing/4/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 24, "col": 20, "resource": "test-files/parsing/4/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 24, "col": 22, "resource": "test-files/parsing/4/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 24, "col": 24, "resource": "test-files/parsing/4/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 24, "col": 25, "resource": "test-files/parsing/4/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 24, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 25, "col": 5, "resource": "test-files/parsing/4/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 25, "col": 11, "resource": "test-files/parsing/4/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 25, "col": 13, "resource": "test-files/parsing/4/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 25, "col": 17, "resource": "test-files/parsing/4/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 25, "col": 18, "resource": "test-files/parsing/4/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 25, "col": 30, "resource": "test-files/parsing/4/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 25, "col": 32, "resource": "test-files/parsing/4/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 25, "col": 35, "resource": "test-files/parsing/4/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 25, "col": 41, "resource": "test-files/parsing/4/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 26, "col": 3, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 28, "col": 1, "resource": "test-files/parsing/4/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/5/tokens b/test-files/parsing/5/tokens index 9479da8..5157abd 100644 --- a/test-files/parsing/5/tokens +++ b/test-files/parsing/5/tokens @@ -1,146 +1,146 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, - {"terminal": "lsquare", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 4, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 4, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 4, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 4, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 5, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 7, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "bG9uZ190YXNr"}, - {"terminal": "lsquare", "line": 7, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 7, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 7, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 7, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 7, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 8, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 8, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 8, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 8, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 8, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 8, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 8, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 8, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "semi", "line": 8, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 11, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 11, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, - {"terminal": "rparen", "line": 11, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 11, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 12, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 12, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 12, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 12, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 12, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 12, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 12, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 13, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 13, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 13, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 13, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 13, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "comma", "line": 13, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 13, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 13, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 13, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "dot", "line": 13, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 13, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "eA=="}, - {"terminal": "semi", "line": 13, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 14, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 14, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 14, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 14, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 14, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ImJhei50eHQi"}, - {"terminal": "rparen", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 14, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 14, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "semi", "line": 14, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 18, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 18, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 18, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 18, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, - {"terminal": "rparen", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 18, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 19, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 19, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 20, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 20, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 20, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 20, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "comma", "line": 20, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 20, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 20, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 20, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "dot", "line": 20, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 20, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "eQ=="}, - {"terminal": "semi", "line": 20, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 21, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 21, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 21, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 21, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 21, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 21, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 21, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 23, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 25, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 25, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, - {"terminal": "lsquare", "line": 25, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 25, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 25, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 25, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 25, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 25, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 26, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 26, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 26, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "comma", "line": 26, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 26, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 26, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 26, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 26, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 27, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 27, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 27, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 27, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 27, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 27, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 27, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "cmVwb3J0"}, - {"terminal": "semi", "line": 27, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 28, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 30, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/5/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/5/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/5/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 8, "resource": "test-files/parsing/5/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 18, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 19, "resource": "test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 26, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 28, "resource": "test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 30, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 4, "col": 13, "resource": "test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 4, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 18, "resource": "test-files/parsing/5/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 4, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 29, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 4, "col": 37, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 7, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 8, "resource": "test-files/parsing/5/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 7, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 18, "resource": "test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 7, "col": 26, "resource": "test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 7, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 29, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 8, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 11, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 13, "resource": "test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 18, "resource": "test-files/parsing/5/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 8, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 8, "col": 29, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 8, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 8, "col": 36, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 11, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 11, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 11, "col": 9, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 11, "col": 14, "resource": "test-files/parsing/5/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 11, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 11, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 11, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 12, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 12, "col": 10, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 12, "col": 15, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 12, "col": 16, "resource": "test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 12, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 12, "col": 24, "resource": "test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 12, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 12, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 13, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 13, "col": 12, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 13, "col": 14, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 13, "col": 16, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 13, "col": 22, "resource": "test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 13, "col": 24, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 13, "col": 26, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 13, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 13, "col": 31, "resource": "test-files/parsing/5/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 13, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 13, "col": 33, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 14, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 14, "col": 13, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 14, "col": 15, "resource": "test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 14, "col": 19, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 14, "col": 20, "resource": "test-files/parsing/5/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 14, "col": 29, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 14, "col": 31, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 14, "col": 34, "resource": "test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 14, "col": 39, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 15, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 16, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 18, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 18, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 18, "col": 9, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 18, "col": 14, "resource": "test-files/parsing/5/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 18, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 18, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 18, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 19, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 10, "resource": "test-files/parsing/5/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 19, "col": 15, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 16, "resource": "test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 24, "resource": "test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 27, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 20, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 20, "col": 12, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 20, "col": 14, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 20, "col": 16, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 20, "col": 21, "resource": "test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 20, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 20, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 20, "col": 26, "resource": "test-files/parsing/5/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 20, "col": 30, "resource": "test-files/parsing/5/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 20, "col": 31, "resource": "test-files/parsing/5/source.wdl", "source_string": "eQ=="}, + {"terminal": "semi", "line": 20, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 21, "col": 7, "resource": "test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 21, "col": 13, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 21, "col": 15, "resource": "test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 21, "col": 19, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 21, "col": 20, "resource": "test-files/parsing/5/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 21, "col": 30, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 21, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 21, "col": 35, "resource": "test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 21, "col": 42, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 22, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 23, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 25, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 25, "col": 8, "resource": "test-files/parsing/5/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 25, "col": 23, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 25, "col": 24, "resource": "test-files/parsing/5/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 25, "col": 31, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 25, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 25, "col": 33, "resource": "test-files/parsing/5/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 25, "col": 35, "resource": "test-files/parsing/5/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 26, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 26, "col": 10, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 26, "col": 12, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 26, "col": 14, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 15, "resource": "test-files/parsing/5/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 26, "col": 20, "resource": "test-files/parsing/5/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 26, "col": 22, "resource": "test-files/parsing/5/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 26, "col": 24, "resource": "test-files/parsing/5/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 26, "col": 25, "resource": "test-files/parsing/5/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 26, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 27, "col": 5, "resource": "test-files/parsing/5/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 27, "col": 11, "resource": "test-files/parsing/5/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 27, "col": 13, "resource": "test-files/parsing/5/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 27, "col": 17, "resource": "test-files/parsing/5/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 27, "col": 18, "resource": "test-files/parsing/5/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 27, "col": 30, "resource": "test-files/parsing/5/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 27, "col": 32, "resource": "test-files/parsing/5/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 27, "col": 35, "resource": "test-files/parsing/5/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 27, "col": 41, "resource": "test-files/parsing/5/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 28, "col": 3, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 30, "col": 1, "resource": "test-files/parsing/5/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/6/tokens b/test-files/parsing/6/tokens index 070200c..836842a 100644 --- a/test-files/parsing/6/tokens +++ b/test-files/parsing/6/tokens @@ -1,160 +1,160 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9v"}, - {"terminal": "lbrace", "line": 1, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 3, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 3, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 3, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, - {"terminal": "rparen", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 4, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 4, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXRhc2s="}, - {"terminal": "lsquare", "line": 4, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 4, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 4, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 5, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 5, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 5, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "comma", "line": 5, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 5, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 5, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "semi", "line": 5, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 6, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 6, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 6, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 6, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 6, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImJhei50eHQi"}, - {"terminal": "rparen", "line": 6, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 6, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 6, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "semi", "line": 6, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 7, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 8, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 10, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 10, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, - {"terminal": "lsquare", "line": 10, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 10, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 10, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 10, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 10, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 11, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 11, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 11, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 11, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 11, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImZvby50eHQi"}, - {"terminal": "rparen", "line": 11, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 11, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 11, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, - {"terminal": "semi", "line": 11, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 12, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 14, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 14, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "bG9uZ190YXNr"}, - {"terminal": "lsquare", "line": 14, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 14, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 14, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 14, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 14, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 14, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 15, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 15, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 15, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 15, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 15, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ImJhci50eHQi"}, - {"terminal": "rparen", "line": 15, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 15, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 15, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "semi", "line": 15, "col": 36, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 16, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 18, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 18, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmF0bWFu"}, - {"terminal": "lsquare", "line": 18, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 18, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 18, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 18, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 18, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 18, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 18, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 19, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 19, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cm9iaW4="}, - {"terminal": "lsquare", "line": 19, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 19, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 19, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 19, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 19, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 19, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 19, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 21, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 21, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, - {"terminal": "lsquare", "line": 21, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 21, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 21, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 21, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 21, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 21, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 22, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 22, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 22, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 22, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 22, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, - {"terminal": "comma", "line": 22, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 22, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 22, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 22, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 22, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 23, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 23, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 23, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 23, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 23, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, - {"terminal": "rparen", "line": 23, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 23, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 23, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cmVwb3J0"}, - {"terminal": "semi", "line": 23, "col": 41, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 24, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 26, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 26, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 26, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 26, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 26, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, - {"terminal": "rparen", "line": 26, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 26, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 27, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 27, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YnRhc2s="}, - {"terminal": "lsquare", "line": 27, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 27, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 27, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 27, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 27, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 27, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 28, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 28, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 28, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 28, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, - {"terminal": "comma", "line": 28, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 28, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 28, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 28, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "semi", "line": 28, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 29, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 29, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 29, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 29, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 29, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, - {"terminal": "rparen", "line": 29, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 29, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 29, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, - {"terminal": "semi", "line": 29, "col": 42, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 30, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 31, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 33, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/6/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/6/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/6/source.wdl", "source_string": "Zm9v"}, + {"terminal": "lbrace", "line": 1, "col": 20, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 3, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 3, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 3, "col": 9, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 3, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 3, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 3, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 3, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 4, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 4, "col": 10, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXRhc2s="}, + {"terminal": "lsquare", "line": 4, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 4, "col": 16, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 4, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 4, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 4, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 4, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 5, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 5, "col": 12, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 5, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 5, "col": 16, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "comma", "line": 5, "col": 22, "resource": "test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 5, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 5, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 5, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "semi", "line": 5, "col": 31, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 6, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 6, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 6, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 6, "col": 19, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 6, "col": 20, "resource": "test-files/parsing/6/source.wdl", "source_string": "ImJhei50eHQi"}, + {"terminal": "rparen", "line": 6, "col": 29, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 6, "col": 31, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 6, "col": 34, "resource": "test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "semi", "line": 6, "col": 39, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 7, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 8, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 10, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 10, "col": 8, "resource": "test-files/parsing/6/source.wdl", "source_string": "c2hvcnRfdGFzaw=="}, + {"terminal": "lsquare", "line": 10, "col": 18, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 10, "col": 19, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 10, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 10, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 10, "col": 28, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 10, "col": 30, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 11, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 11, "col": 11, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 11, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 11, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 11, "col": 18, "resource": "test-files/parsing/6/source.wdl", "source_string": "ImZvby50eHQi"}, + {"terminal": "rparen", "line": 11, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 11, "col": 29, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 11, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "YWxwaGE="}, + {"terminal": "semi", "line": 11, "col": 37, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 12, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 14, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 14, "col": 8, "resource": "test-files/parsing/6/source.wdl", "source_string": "bG9uZ190YXNr"}, + {"terminal": "lsquare", "line": 14, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 14, "col": 18, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 14, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 14, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 14, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 14, "col": 29, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 15, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 15, "col": 11, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 15, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 15, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 15, "col": 18, "resource": "test-files/parsing/6/source.wdl", "source_string": "ImJhci50eHQi"}, + {"terminal": "rparen", "line": 15, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 15, "col": 29, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 15, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "semi", "line": 15, "col": 36, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 16, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 18, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 18, "col": 8, "resource": "test-files/parsing/6/source.wdl", "source_string": "YmF0bWFu"}, + {"terminal": "lsquare", "line": 18, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 18, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 18, "col": 22, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 18, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 18, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 18, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 18, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 19, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 19, "col": 8, "resource": "test-files/parsing/6/source.wdl", "source_string": "cm9iaW4="}, + {"terminal": "lsquare", "line": 19, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 19, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 19, "col": 21, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 19, "col": 22, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 19, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 19, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 19, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 21, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 21, "col": 8, "resource": "test-files/parsing/6/source.wdl", "source_string": "Z2VuZXJhdGVfcmVwb3J0"}, + {"terminal": "lsquare", "line": 21, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 21, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 21, "col": 31, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 21, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 21, "col": 33, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 21, "col": 35, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 22, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 22, "col": 10, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 22, "col": 12, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 22, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 22, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "Z2FtbWE="}, + {"terminal": "comma", "line": 22, "col": 20, "resource": "test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 22, "col": 22, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 22, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 22, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 22, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 23, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 23, "col": 11, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 23, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 23, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 23, "col": 18, "resource": "test-files/parsing/6/source.wdl", "source_string": "InJlcG9ydC50eHQi"}, + {"terminal": "rparen", "line": 23, "col": 30, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 23, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 23, "col": 35, "resource": "test-files/parsing/6/source.wdl", "source_string": "cmVwb3J0"}, + {"terminal": "semi", "line": 23, "col": 41, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 24, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 26, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 26, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 26, "col": 9, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 26, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 26, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbXM="}, + {"terminal": "rparen", "line": 26, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 26, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 27, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 27, "col": 10, "resource": "test-files/parsing/6/source.wdl", "source_string": "YnRhc2s="}, + {"terminal": "lsquare", "line": 27, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 27, "col": 16, "resource": "test-files/parsing/6/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 27, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 27, "col": 24, "resource": "test-files/parsing/6/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 27, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 27, "col": 27, "resource": "test-files/parsing/6/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 28, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 28, "col": 12, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 28, "col": 14, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 28, "col": 16, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 17, "resource": "test-files/parsing/6/source.wdl", "source_string": "YmV0YQ=="}, + {"terminal": "comma", "line": 28, "col": 21, "resource": "test-files/parsing/6/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 28, "col": 23, "resource": "test-files/parsing/6/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 28, "col": 25, "resource": "test-files/parsing/6/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 28, "col": 26, "resource": "test-files/parsing/6/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "semi", "line": 28, "col": 30, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 29, "col": 7, "resource": "test-files/parsing/6/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 29, "col": 13, "resource": "test-files/parsing/6/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 29, "col": 15, "resource": "test-files/parsing/6/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 29, "col": 19, "resource": "test-files/parsing/6/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 29, "col": 20, "resource": "test-files/parsing/6/source.wdl", "source_string": "InF1dXgudHh0Ig=="}, + {"terminal": "rparen", "line": 29, "col": 30, "resource": "test-files/parsing/6/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 29, "col": 32, "resource": "test-files/parsing/6/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 29, "col": 35, "resource": "test-files/parsing/6/source.wdl", "source_string": "ZXBzaWxvbg=="}, + {"terminal": "semi", "line": 29, "col": 42, "resource": "test-files/parsing/6/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 30, "col": 5, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 31, "col": 3, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 33, "col": 1, "resource": "test-files/parsing/6/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/7/tokens b/test-files/parsing/7/tokens index 3094fbc..b200998 100644 --- a/test-files/parsing/7/tokens +++ b/test-files/parsing/7/tokens @@ -1,63 +1,63 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGVzdA=="}, - {"terminal": "lbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 2, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "in", "line": 2, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 2, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Y29sbGVjdGlvbg=="}, - {"terminal": "rparen", "line": 2, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 2, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 3, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGFzaw=="}, - {"terminal": "lsquare", "line": 3, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 3, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 3, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 3, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 3, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 4, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 4, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 4, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 4, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eA=="}, - {"terminal": "comma", "line": 4, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 4, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 4, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eQ=="}, - {"terminal": "comma", "line": 4, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 4, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 4, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 4, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, - {"terminal": "dot", "line": 4, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Lg=="}, - {"terminal": "identifier", "line": 4, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "eg=="}, - {"terminal": "semi", "line": 4, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 5, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 5, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 5, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 5, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 5, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Inh5eiI="}, - {"terminal": "rparen", "line": 5, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 5, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 5, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, - {"terminal": "semi", "line": 5, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 6, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 7, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 9, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 9, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dGFzazE="}, - {"terminal": "lsquare", "line": 9, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 9, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 9, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 10, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 10, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 10, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 10, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, - {"terminal": "semi", "line": 10, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 12, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/7/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/7/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/7/source.wdl", "source_string": "dGVzdA=="}, + {"terminal": "lbrace", "line": 1, "col": 21, "resource": "test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 2, "col": 3, "resource": "test-files/parsing/7/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 2, "col": 7, "resource": "test-files/parsing/7/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "in", "line": 2, "col": 13, "resource": "test-files/parsing/7/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 2, "col": 16, "resource": "test-files/parsing/7/source.wdl", "source_string": "Y29sbGVjdGlvbg=="}, + {"terminal": "rparen", "line": 2, "col": 26, "resource": "test-files/parsing/7/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 2, "col": 28, "resource": "test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 3, "col": 5, "resource": "test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 3, "col": 10, "resource": "test-files/parsing/7/source.wdl", "source_string": "dGFzaw=="}, + {"terminal": "lsquare", "line": 3, "col": 14, "resource": "test-files/parsing/7/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 3, "col": 15, "resource": "test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 3, "col": 22, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 3, "col": 23, "resource": "test-files/parsing/7/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 3, "col": 24, "resource": "test-files/parsing/7/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 3, "col": 26, "resource": "test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 4, "col": 7, "resource": "test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 4, "col": 12, "resource": "test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 4, "col": 14, "resource": "test-files/parsing/7/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 4, "col": 16, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 17, "resource": "test-files/parsing/7/source.wdl", "source_string": "eA=="}, + {"terminal": "comma", "line": 4, "col": 18, "resource": "test-files/parsing/7/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 20, "resource": "test-files/parsing/7/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 4, "col": 22, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 23, "resource": "test-files/parsing/7/source.wdl", "source_string": "eQ=="}, + {"terminal": "comma", "line": 4, "col": 24, "resource": "test-files/parsing/7/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 4, "col": 26, "resource": "test-files/parsing/7/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 4, "col": 28, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 4, "col": 29, "resource": "test-files/parsing/7/source.wdl", "source_string": "aXRlbQ=="}, + {"terminal": "dot", "line": 4, "col": 33, "resource": "test-files/parsing/7/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 4, "col": 34, "resource": "test-files/parsing/7/source.wdl", "source_string": "eg=="}, + {"terminal": "semi", "line": 4, "col": 35, "resource": "test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 5, "col": 7, "resource": "test-files/parsing/7/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 5, "col": 13, "resource": "test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 5, "col": 15, "resource": "test-files/parsing/7/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 5, "col": 19, "resource": "test-files/parsing/7/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 5, "col": 20, "resource": "test-files/parsing/7/source.wdl", "source_string": "Inh5eiI="}, + {"terminal": "rparen", "line": 5, "col": 25, "resource": "test-files/parsing/7/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 5, "col": 27, "resource": "test-files/parsing/7/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 5, "col": 30, "resource": "test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, + {"terminal": "semi", "line": 5, "col": 34, "resource": "test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 6, "col": 5, "resource": "test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 7, "col": 3, "resource": "test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 9, "col": 3, "resource": "test-files/parsing/7/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 9, "col": 8, "resource": "test-files/parsing/7/source.wdl", "source_string": "dGFzazE="}, + {"terminal": "lsquare", "line": 9, "col": 13, "resource": "test-files/parsing/7/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 9, "col": 14, "resource": "test-files/parsing/7/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 9, "col": 21, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 9, "col": 22, "resource": "test-files/parsing/7/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 9, "col": 23, "resource": "test-files/parsing/7/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 9, "col": 25, "resource": "test-files/parsing/7/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 10, "col": 5, "resource": "test-files/parsing/7/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 10, "col": 10, "resource": "test-files/parsing/7/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 10, "col": 12, "resource": "test-files/parsing/7/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 10, "col": 14, "resource": "test-files/parsing/7/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 10, "col": 15, "resource": "test-files/parsing/7/source.wdl", "source_string": "bGlzdA=="}, + {"terminal": "semi", "line": 10, "col": 19, "resource": "test-files/parsing/7/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 3, "resource": "test-files/parsing/7/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 12, "col": 1, "resource": "test-files/parsing/7/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/8/tokens b/test-files/parsing/8/tokens index a5d3bee..2608312 100644 --- a/test-files/parsing/8/tokens +++ b/test-files/parsing/8/tokens @@ -1,87 +1,87 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dGVzdA=="}, - {"terminal": "lbrace", "line": 1, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 2, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 2, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czA="}, - {"terminal": "lsquare", "line": 2, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 2, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 2, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 2, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 2, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 2, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "output", "line": 3, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 3, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 3, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 3, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 3, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ImFiYyI="}, - {"terminal": "rparen", "line": 3, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 3, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 3, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, - {"terminal": "semi", "line": 3, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 4, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, - {"terminal": "for", "line": 6, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 6, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 6, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "SQ=="}, - {"terminal": "in", "line": 6, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 6, "col": 13, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "TA=="}, - {"terminal": "rparen", "line": 6, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 6, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "for", "line": 7, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, - {"terminal": "lparen", "line": 7, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, - {"terminal": "identifier", "line": 7, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Sg=="}, - {"terminal": "in", "line": 7, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW4="}, - {"terminal": "identifier", "line": 7, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "TQ=="}, - {"terminal": "rparen", "line": 7, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, - {"terminal": "lbrace", "line": 7, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 8, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 8, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czE="}, - {"terminal": "lsquare", "line": 8, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 8, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 8, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 8, "col": 23, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 8, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 8, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 9, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 9, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 9, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 9, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "SQ=="}, - {"terminal": "comma", "line": 9, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDE="}, - {"terminal": "assign", "line": 9, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Sg=="}, - {"terminal": "comma", "line": 9, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "LA=="}, - {"terminal": "identifier", "line": 9, "col": 28, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDI="}, - {"terminal": "assign", "line": 9, "col": 30, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 9, "col": 31, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, - {"terminal": "semi", "line": 9, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, - {"terminal": "output", "line": 10, "col": 9, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, - {"terminal": "colon", "line": 10, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, - {"terminal": "file", "line": 10, "col": 17, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, - {"terminal": "lparen", "line": 10, "col": 21, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KA=="}, - {"terminal": "string", "line": 10, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ImRlZiI="}, - {"terminal": "rparen", "line": 10, "col": 27, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "KQ=="}, - {"terminal": "as", "line": 10, "col": 29, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YXM="}, - {"terminal": "identifier", "line": 10, "col": 32, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YmFy"}, - {"terminal": "semi", "line": 10, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 11, "col": 7, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 12, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 13, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, - {"terminal": "step", "line": 15, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 15, "col": 8, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "czI="}, - {"terminal": "lsquare", "line": 15, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 15, "col": 11, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 15, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 15, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 15, "col": 20, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 15, "col": 22, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "ew=="}, - {"terminal": "input", "line": 16, "col": 5, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, - {"terminal": "colon", "line": 16, "col": 10, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Og=="}, - {"terminal": "identifier", "line": 16, "col": 12, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "cDA="}, - {"terminal": "assign", "line": 16, "col": 14, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "PQ=="}, - {"terminal": "identifier", "line": 16, "col": 15, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "YmFy"}, - {"terminal": "semi", "line": 16, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "Ow=="}, - {"terminal": "rbrace", "line": 17, "col": 3, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 18, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/8/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/8/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/8/source.wdl", "source_string": "dGVzdA=="}, + {"terminal": "lbrace", "line": 1, "col": 21, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/8/source.wdl", "source_string": "czA="}, + {"terminal": "lsquare", "line": 2, "col": 10, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 11, "resource": "test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 2, "col": 19, "resource": "test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 2, "col": 20, "resource": "test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 22, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "output", "line": 3, "col": 5, "resource": "test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 3, "col": 11, "resource": "test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 3, "col": 13, "resource": "test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 3, "col": 17, "resource": "test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 3, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "ImFiYyI="}, + {"terminal": "rparen", "line": 3, "col": 23, "resource": "test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 3, "col": 25, "resource": "test-files/parsing/8/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 3, "col": 28, "resource": "test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, + {"terminal": "semi", "line": 3, "col": 31, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 4, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 6, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 6, "col": 7, "resource": "test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 6, "col": 8, "resource": "test-files/parsing/8/source.wdl", "source_string": "SQ=="}, + {"terminal": "in", "line": 6, "col": 10, "resource": "test-files/parsing/8/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 6, "col": 13, "resource": "test-files/parsing/8/source.wdl", "source_string": "TA=="}, + {"terminal": "rparen", "line": 6, "col": 14, "resource": "test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 6, "col": 16, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "for", "line": 7, "col": 5, "resource": "test-files/parsing/8/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 7, "col": 9, "resource": "test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 7, "col": 10, "resource": "test-files/parsing/8/source.wdl", "source_string": "Sg=="}, + {"terminal": "in", "line": 7, "col": 12, "resource": "test-files/parsing/8/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 7, "col": 15, "resource": "test-files/parsing/8/source.wdl", "source_string": "TQ=="}, + {"terminal": "rparen", "line": 7, "col": 16, "resource": "test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 7, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 8, "col": 7, "resource": "test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 8, "col": 12, "resource": "test-files/parsing/8/source.wdl", "source_string": "czE="}, + {"terminal": "lsquare", "line": 8, "col": 14, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 8, "col": 15, "resource": "test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 8, "col": 22, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 8, "col": 23, "resource": "test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 8, "col": 24, "resource": "test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 8, "col": 26, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 9, "col": 9, "resource": "test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 9, "col": 14, "resource": "test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 9, "col": 16, "resource": "test-files/parsing/8/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 9, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 19, "resource": "test-files/parsing/8/source.wdl", "source_string": "SQ=="}, + {"terminal": "comma", "line": 9, "col": 20, "resource": "test-files/parsing/8/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 22, "resource": "test-files/parsing/8/source.wdl", "source_string": "cDE="}, + {"terminal": "assign", "line": 9, "col": 24, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 25, "resource": "test-files/parsing/8/source.wdl", "source_string": "Sg=="}, + {"terminal": "comma", "line": 9, "col": 26, "resource": "test-files/parsing/8/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 9, "col": 28, "resource": "test-files/parsing/8/source.wdl", "source_string": "cDI="}, + {"terminal": "assign", "line": 9, "col": 30, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 9, "col": 31, "resource": "test-files/parsing/8/source.wdl", "source_string": "Zm9v"}, + {"terminal": "semi", "line": 9, "col": 34, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 10, "col": 9, "resource": "test-files/parsing/8/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 10, "col": 15, "resource": "test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 10, "col": 17, "resource": "test-files/parsing/8/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 10, "col": 21, "resource": "test-files/parsing/8/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 10, "col": 22, "resource": "test-files/parsing/8/source.wdl", "source_string": "ImRlZiI="}, + {"terminal": "rparen", "line": 10, "col": 27, "resource": "test-files/parsing/8/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 10, "col": 29, "resource": "test-files/parsing/8/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 10, "col": 32, "resource": "test-files/parsing/8/source.wdl", "source_string": "YmFy"}, + {"terminal": "semi", "line": 10, "col": 35, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 11, "col": 7, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 12, "col": 5, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 13, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "step", "line": 15, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 15, "col": 8, "resource": "test-files/parsing/8/source.wdl", "source_string": "czI="}, + {"terminal": "lsquare", "line": 15, "col": 10, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 15, "col": 11, "resource": "test-files/parsing/8/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 15, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 15, "col": 19, "resource": "test-files/parsing/8/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 15, "col": 20, "resource": "test-files/parsing/8/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 15, "col": 22, "resource": "test-files/parsing/8/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 16, "col": 5, "resource": "test-files/parsing/8/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 16, "col": 10, "resource": "test-files/parsing/8/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 16, "col": 12, "resource": "test-files/parsing/8/source.wdl", "source_string": "cDA="}, + {"terminal": "assign", "line": 16, "col": 14, "resource": "test-files/parsing/8/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 16, "col": 15, "resource": "test-files/parsing/8/source.wdl", "source_string": "YmFy"}, + {"terminal": "semi", "line": 16, "col": 18, "resource": "test-files/parsing/8/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 17, "col": 3, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 18, "col": 1, "resource": "test-files/parsing/8/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/parsing/9/tokens b/test-files/parsing/9/tokens index 463067f..2a0b8d5 100644 --- a/test-files/parsing/9/tokens +++ b/test-files/parsing/9/tokens @@ -1,15 +1,15 @@ [ - {"terminal": "composite_task", "line": 1, "col": 1, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, - {"terminal": "identifier", "line": 1, "col": 16, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "eA=="}, - {"terminal": "lbrace", "line": 1, "col": 18, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "ew=="}, - {"terminal": "step", "line": 1, "col": 19, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "c3RlcA=="}, - {"terminal": "identifier", "line": 1, "col": 24, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "eQ=="}, - {"terminal": "lsquare", "line": 1, "col": 25, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "Ww=="}, - {"terminal": "identifier", "line": 1, "col": 26, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "dmVyc2lvbg=="}, - {"terminal": "assign", "line": 1, "col": 33, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "PQ=="}, - {"terminal": "number", "line": 1, "col": 34, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "MA=="}, - {"terminal": "rsquare", "line": 1, "col": 35, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "XQ=="}, - {"terminal": "lbrace", "line": 1, "col": 37, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "ew=="}, - {"terminal": "rbrace", "line": 1, "col": 38, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "fQ=="}, - {"terminal": "rbrace", "line": 1, "col": 39, "resource": "/Users/sfrazer/projects/wdl/test-files/parsing/9/source.wdl", "source_string": "fQ=="} + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/9/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/9/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "test-files/parsing/9/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 1, "col": 19, "resource": "test-files/parsing/9/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 1, "col": 24, "resource": "test-files/parsing/9/source.wdl", "source_string": "eQ=="}, + {"terminal": "lsquare", "line": 1, "col": 25, "resource": "test-files/parsing/9/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 1, "col": 26, "resource": "test-files/parsing/9/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 1, "col": 33, "resource": "test-files/parsing/9/source.wdl", "source_string": "PQ=="}, + {"terminal": "number", "line": 1, "col": 34, "resource": "test-files/parsing/9/source.wdl", "source_string": "MA=="}, + {"terminal": "rsquare", "line": 1, "col": 35, "resource": "test-files/parsing/9/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 1, "col": 37, "resource": "test-files/parsing/9/source.wdl", "source_string": "ew=="}, + {"terminal": "rbrace", "line": 1, "col": 38, "resource": "test-files/parsing/9/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 1, "col": 39, "resource": "test-files/parsing/9/source.wdl", "source_string": "fQ=="} ] diff --git a/test-files/syntax-error/0/errors b/test-files/syntax-error/0/errors index 0007b12..9578141 100644 --- a/test-files/syntax-error/0/errors +++ b/test-files/syntax-error/0/errors @@ -1,5 +1,5 @@ org.broadinstitute.parser.SyntaxError: Step 'btask' inside for loop doesn't use loop iterator: item -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/0/source.wdl @ line 8, column 10: +Location: test-files/syntax-error/0/source.wdl @ line 8, column 10: step btask[version=0] { ^ diff --git a/test-files/syntax-error/1/errors b/test-files/syntax-error/1/errors index 938fcda..cf6a838 100644 --- a/test-files/syntax-error/1/errors +++ b/test-files/syntax-error/1/errors @@ -1,5 +1,5 @@ org.broadinstitute.parser.SyntaxError: Two steps output to the same variable: x -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/1/source.wdl @ line 9, column 35: +Location: test-files/syntax-error/1/source.wdl @ line 9, column 35: output: File("report.txt") as x; ^ diff --git a/test-files/syntax-error/2/errors b/test-files/syntax-error/2/errors index 278b082..9914f9e 100644 --- a/test-files/syntax-error/2/errors +++ b/test-files/syntax-error/2/errors @@ -1,5 +1,5 @@ org.broadinstitute.parser.SyntaxError: Two steps output to the same file: "foo.txt" -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/2/source.wdl @ line 9, column 18: +Location: test-files/syntax-error/2/source.wdl @ line 9, column 18: output: File("foo.txt") as xyz; ^ diff --git a/test-files/syntax-error/3/errors b/test-files/syntax-error/3/errors index d05934b..3f5bae9 100644 --- a/test-files/syntax-error/3/errors +++ b/test-files/syntax-error/3/errors @@ -1,5 +1,5 @@ org.broadinstitute.parser.SyntaxError: Two steps have the same name: atask -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/3/source.wdl @ line 7, column 8: +Location: test-files/syntax-error/3/source.wdl @ line 7, column 8: step atask[version=0] { ^ diff --git a/test-files/syntax-error/4/errors b/test-files/syntax-error/4/errors index f325fa3..49f0bfc 100644 --- a/test-files/syntax-error/4/errors +++ b/test-files/syntax-error/4/errors @@ -1,5 +1,5 @@ org.broadinstitute.parser.SyntaxError: Version information missing for task x -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/4/source.wdl @ line 3, column 8: +Location: test-files/syntax-error/4/source.wdl @ line 3, column 8: step x {} ^ diff --git a/test-files/syntax-error/5/errors b/test-files/syntax-error/5/errors index 13468aa..24f1d24 100644 --- a/test-files/syntax-error/5/errors +++ b/test-files/syntax-error/5/errors @@ -1,6 +1,6 @@ org.broadinstitute.parser.SyntaxError: Unexpected symbol identifier. Expecting composite_task. Rule: wdl := _gen0 -Location: /Users/sfrazer/projects/wdl/test-files/syntax-error/5/source.wdl @ line 1, column 1: +Location: test-files/syntax-error/5/source.wdl @ line 1, column 1: composite task foo {} ^ From efb44bb372c24e6fd5d7d1e4a490bb9dd81a57fd Mon Sep 17 00:00:00 2001 From: Pei Lin Date: Thu, 13 Dec 2012 15:14:14 -0500 Subject: [PATCH 120/140] make the verticies in CompositeTaskGraph preserve the order that they were added --- .../compositetask/CompositeTaskGraph.java | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java index c074e12..60b45a9 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskGraph.java @@ -4,7 +4,7 @@ import java.util.Collection; import java.util.Map; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Comparator; import java.util.Collections; import java.util.Iterator; @@ -19,8 +19,8 @@ public CompositeTaskGraph(CompositeTask composite_task) { this.scope_output_map = new HashMap>(); this.edge_factory = new CompositeTaskEdgeFactory(); - this.verticies = new HashSet(); - this.edges = new HashSet(); + this.verticies = new LinkedHashSet(); + this.edges = new LinkedHashSet(); generate_scope_output(composite_task); generate_graph(composite_task); @@ -79,7 +79,7 @@ public int compare(CompositeTaskScope s1, CompositeTaskScope s2) { } private CompositeTaskScope closest_scope(CompositeTaskNode node, Set scopes) { - Set matches = new HashSet(); + Set matches = new LinkedHashSet(); for ( CompositeTaskScope scope : scopes ) { if ( node.getParent().contains(scope) ) { matches.add(scope); @@ -99,7 +99,7 @@ private void generate_scope_output(CompositeTaskScope scope) { Set scope_outputs = get_outputs(sub_scope); for ( CompositeTaskVariable variable : scope_outputs ) { if ( !scope_output_map.containsKey(variable) ) { - scope_output_map.put(variable, new HashSet()); + scope_output_map.put(variable, new LinkedHashSet()); } scope_output_map.get(variable).add(sub_scope); generate_scope_output(sub_scope); @@ -109,7 +109,7 @@ private void generate_scope_output(CompositeTaskScope scope) { } private Set get_outputs(CompositeTaskScope scope) { - Set outputs = new HashSet(); + Set outputs = new LinkedHashSet(); for ( CompositeTaskNode node : scope.getNodes() ) { if ( node instanceof CompositeTaskStep ) { CompositeTaskStep step = (CompositeTaskStep) node; @@ -199,7 +199,7 @@ public boolean containsVertex(CompositeTaskVertex v) { throw new IllegalArgumentException("edgesOf(): vertex is not in graph"); } - Set edges = new HashSet(); + Set edges = new LinkedHashSet(); for ( CompositeTaskEdge edge : this.edges ) { if ( edge.getStart().equals(vertex) || edge.getEnd().equals(vertex) ) { edges.add(edge); @@ -213,7 +213,7 @@ public boolean removeAllEdges(Collection edges) { throw new NullPointerException("removeAllEdges(): null edge collection"); } - Set removed_edges = new HashSet(); + Set removed_edges = new LinkedHashSet(); for ( CompositeTaskEdge edge : this.edges ) { if (edges.contains(edge)) { removed_edges.add(edge); @@ -235,7 +235,7 @@ public boolean removeAllEdges(Collection edges) { return null; } - Set edges = new HashSet(); + Set edges = new LinkedHashSet(); while ( true ) { CompositeTaskEdge removed_edge = removeEdge(sourceVertex, targetVertex); if ( removed_edge == null ) { @@ -251,7 +251,7 @@ public boolean removeAllVertices(Collection verti throw new NullPointerException("removeAllVerticies(): null edge collection"); } - Set removed_verticies = new HashSet(); + Set removed_verticies = new LinkedHashSet(); for ( CompositeTaskVertex vertex : this.verticies ) { if (verticies.contains(vertex)) { removed_verticies.add(vertex); @@ -333,7 +333,7 @@ public int inDegreeOf(CompositeTaskVertex vertex) { } public Set incomingEdgesOf(CompositeTaskVertex vertex) { - Set incoming = new HashSet(); + Set incoming = new LinkedHashSet(); for ( CompositeTaskEdge edge : this.edges ) { if ( edge.getEnd().equals(vertex) ) { incoming.add(edge); @@ -353,7 +353,7 @@ public int outDegreeOf(CompositeTaskVertex vertex) { } public Set outgoingEdgesOf(CompositeTaskVertex vertex) { - Set outgoing = new HashSet(); + Set outgoing = new LinkedHashSet(); for ( CompositeTaskEdge edge : this.edges ) { if ( edge.getStart().equals(vertex) ) { outgoing.add(edge); From e2b8cd994466d7d46e8e74fca8df7ea2d03d9841 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 11 Mar 2013 14:12:00 -0400 Subject: [PATCH 121/140] Allowing for dots in parameter names (GP compatibility) and removing a syntax error --- .../java/org/broadinstitute/compositetask/CompositeTask.java | 5 ++++- .../compositetask/CompositeTaskSourceCodeFormatter.java | 6 +++--- .../compositetask/CompositeTaskStepOutput.java | 2 +- src/main/java/org/broadinstitute/compositetask/Lexer.java | 1 + test-files/syntax-error/2/errors | 12 ++++++------ test-files/syntax-error/2/source.wdl | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 9686b00..9cbd934 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -183,7 +183,10 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { } if (this.output_files.containsKey(filepath.getSourceString())) { - throw new SyntaxError(this.syntaxErrorFormatter.duplicate_output_file(filepath, this.output_files.get(filepath.getSourceString()))); + // We don't need this syntax error anymore, but perhaps useful in the future. */ + /* throw new SyntaxError( + this.syntaxErrorFormatter.duplicate_output_file(filepath, this.output_files.get(filepath.getSourceString()))); + */ } else { this.output_files.put(filepath.getSourceString(), filepath); } diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java index 8afcd48..9af6334 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskSourceCodeFormatter.java @@ -8,11 +8,11 @@ public class CompositeTaskSourceCodeFormatter { private CompositeTaskColorizer colorizer; - CompositeTaskSourceCodeFormatter(CompositeTaskColorizer colorizer) { + public CompositeTaskSourceCodeFormatter(CompositeTaskColorizer colorizer) { this.colorizer = colorizer; } - CompositeTaskSourceCodeFormatter() { + public CompositeTaskSourceCodeFormatter() { this(new NullColorizer()); } @@ -58,7 +58,7 @@ private String format(CompositeTaskNode node, int indent) { if ( step.getOutputs().size() > 0 ) { List outputs = new ArrayList(); for ( CompositeTaskStepOutput output : step.getOutputs() ) { - outputs.add(output.getType() + "(" + this.colorizer.string(output.getPath()) + ") " + this.colorizer.keyword("as") + " " + this.colorizer.variable(variable_to_string(output.getVariable()))); + outputs.add(output.getType() + "(\"" + this.colorizer.string(output.getPath()) + "\") " + this.colorizer.keyword("as") + " " + this.colorizer.variable(variable_to_string(output.getVariable()))); } builder.append(indent_str + " " + this.colorizer.keyword("output") + ": " + Utility.join(outputs, ", ") + ";\n"); diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java index 5c4ec60..2a590be 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTaskStepOutput.java @@ -22,7 +22,7 @@ public Ast getAst() { } public String getPath() { - return this.path; + return this.path.replaceAll("^\"|\"$", ""); } public String getMethod() { diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index 2314da5..677bc39 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -79,6 +79,7 @@ public String toString() { this.regex.add( new TokenLexer(Pattern.compile("^\\("), CompositeTaskParser.TerminalId.TERMINAL_LPAREN) ); this.regex.add( new TokenLexer(Pattern.compile("^\\)"), CompositeTaskParser.TerminalId.TERMINAL_RPAREN) ); this.regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), CompositeTaskParser.TerminalId.TERMINAL_STRING) ); + this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z0-9_\\.])+(?=\\s*=)"), CompositeTaskParser.TerminalId.TERMINAL_IDENTIFIER) ); this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), CompositeTaskParser.TerminalId.TERMINAL_IDENTIFIER) ); this.regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), CompositeTaskParser.TerminalId.TERMINAL_NUMBER) ); this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) ); diff --git a/test-files/syntax-error/2/errors b/test-files/syntax-error/2/errors index 9914f9e..7bece5f 100644 --- a/test-files/syntax-error/2/errors +++ b/test-files/syntax-error/2/errors @@ -1,9 +1,9 @@ -org.broadinstitute.parser.SyntaxError: Two steps output to the same file: "foo.txt" -Location: test-files/syntax-error/2/source.wdl @ line 9, column 18: +org.broadinstitute.parser.SyntaxError: Two steps output to the same variable: xyz +Location: test-files/syntax-error/2/source.wdl @ line 9, column 32: output: File("foo.txt") as xyz; - ^ -Previous output for file was @ line 4, column 18: + ^ +Previous output for variable was @ line 4, column 32: - output: File("foo.txt") as abc; - ^ + output: File("foo.txt") as xyz; + ^ diff --git a/test-files/syntax-error/2/source.wdl b/test-files/syntax-error/2/source.wdl index 5213c5b..6c7b688 100644 --- a/test-files/syntax-error/2/source.wdl +++ b/test-files/syntax-error/2/source.wdl @@ -1,7 +1,7 @@ composite_task foo { step atask[version=0] { - output: File("foo.txt") as abc; + output: File("foo.txt") as xyz; } step btask[version=0] { From 32a513f5f3b802692333524bb28b8ae4f29c86c2 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 22 Mar 2013 11:01:19 -0400 Subject: [PATCH 122/140] Changing the lexical analysis of the 'input' keyword --- src/main/java/org/broadinstitute/compositetask/Lexer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index 677bc39..f399f39 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -60,7 +60,7 @@ public String toString() { this.regex.add( new TokenLexer(Pattern.compile("^//.*"), null) ); this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); - this.regex.add( new TokenLexer(Pattern.compile("^input(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^input(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); From fbd7a99e9905ffc8a1b0d20d3f71b3fe597f0768 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Tue, 2 Apr 2013 15:25:26 -0400 Subject: [PATCH 123/140] Fixing bug in lexical analyzer that won't allow for parameters to start with 'output' --- src/main/java/org/broadinstitute/compositetask/Lexer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index f399f39..ec920a3 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -59,7 +59,7 @@ public String toString() { this.regex.add( new TokenLexer(Pattern.compile("^/\\*.*?\\*/", Pattern.DOTALL), null) ); this.regex.add( new TokenLexer(Pattern.compile("^//.*"), null) ); this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) ); - this.regex.add( new TokenLexer(Pattern.compile("^output(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); + this.regex.add( new TokenLexer(Pattern.compile("^output(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) ); this.regex.add( new TokenLexer(Pattern.compile("^input(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); From b32c41f6ebd58f7ae18f42445703a2fa8b1d3934 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 9 Sep 2013 15:01:26 -0400 Subject: [PATCH 124/140] Beginning of support for FirstLine() directives for task outputs --- grammars/composite_task.zgr | 3 ++- src/main/java/org/broadinstitute/compositetask/Lexer.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/grammars/composite_task.zgr b/grammars/composite_task.zgr index 288c5b7..2e08bad 100644 --- a/grammars/composite_task.zgr +++ b/grammars/composite_task.zgr @@ -17,7 +17,8 @@ "step_input_list := 'input' + 'colon' + list(step_input, 'comma') + 'semi' -> StepInputList( inputs=$2 )", "step_input := 'identifier' + 'assign' + variable -> StepInput(parameter=$0, value=$2)", "step_output_list := 'output' + 'colon' + list(step_output, 'comma') + 'semi' -> StepOutputList( outputs=$2 )", - "step_output := 'file' + 'lparen' + 'string' + 'rparen' + step_output_location -> StepFileOutput( file=$2, var=$4 )", + "step_output := step_output_mode + 'lparen' + 'string' + 'rparen' + step_output_location -> StepOutput( mode=$0, expression=$2, var=$4 )", + "step_output_mode := 'file' | 'first_line'", "step_output_location := 'as' + variable -> OutputVariable( var=$1 )", "step_output_location := 'into' + variable -> OutputListAppend( var=$1 )", "variable := 'identifier' + optional(variable_member) -> Variable(name=$0, member=$1)", diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java index ec920a3..3784700 100644 --- a/src/main/java/org/broadinstitute/compositetask/Lexer.java +++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java @@ -63,6 +63,7 @@ public String toString() { this.regex.add( new TokenLexer(Pattern.compile("^input(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) ); this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) ); this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) ); + this.regex.add( new TokenLexer(Pattern.compile("^FirstLine(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FIRST_LINE) ); this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) ); this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) ); this.regex.add( new TokenLexer(Pattern.compile("^into(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INTO) ); From 02be66e29e716f4eea8ce813d76b3d605fb05af9 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 15:53:21 -0400 Subject: [PATCH 125/140] Generate new parser --- .../broadinstitute/parser/CompositeTaskParser.java | 1388 ++++++++++---------- 1 file changed, 717 insertions(+), 671 deletions(-) diff --git a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java index 43a7ffe..734866d 100644 --- a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java +++ b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java @@ -14,61 +14,63 @@ private Map rules; /* table[nonterminal][terminal] = rule */ private static final int[][] table = { - { -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 46, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 37, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, 7, -1, 8, -1, -1, -1, -1 }, - { -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 35, 20, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1 }, - { -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24 }, - { -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, 36, -1, -1, -1, -1 }, - { -1, -1, 0, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1 }, + { -1, -1, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1 }, + { 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 42, -1 }, + { -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 0, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, 8, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1 }, + { -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1 }, + { -1, 43, -1, -1, -1, -1, -1, -1, 16, -1, 16, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 13, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 18, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20 }, + { -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, 41, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 }, + { -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, }; public enum TerminalId implements TerminalIdentifier { - TERMINAL_FOR(0, "for"), - TERMINAL_RSQUARE(1, "rsquare"), - TERMINAL_AS(2, "as"), - TERMINAL_IN(3, "in"), - TERMINAL_ASSIGN(4, "assign"), - TERMINAL_RPAREN(5, "rparen"), - TERMINAL_LSQUARE(6, "lsquare"), - TERMINAL_OUTPUT(7, "output"), - TERMINAL_INPUT(8, "input"), - TERMINAL_FILE(9, "file"), - TERMINAL_COMMA(10, "comma"), - TERMINAL_STEP(11, "step"), - TERMINAL_COMPOSITE_TASK(12, "composite_task"), - TERMINAL_IDENTIFIER(13, "identifier"), - TERMINAL_STRING(14, "string"), + TERMINAL_RSQUARE(0, "rsquare"), + TERMINAL_RBRACE(1, "rbrace"), + TERMINAL_DOT(2, "dot"), + TERMINAL_FILE(3, "file"), + TERMINAL_COMMA(4, "comma"), + TERMINAL_OUTPUT(5, "output"), + TERMINAL_LBRACE(6, "lbrace"), + TERMINAL_INTO(7, "into"), + TERMINAL_FOR(8, "for"), + TERMINAL_STRING(9, "string"), + TERMINAL_COMPOSITE_TASK(10, "composite_task"), + TERMINAL_IDENTIFIER(11, "identifier"), + TERMINAL_IN(12, "in"), + TERMINAL_RPAREN(13, "rparen"), + TERMINAL_STEP(14, "step"), TERMINAL_NUMBER(15, "number"), - TERMINAL_DOT(16, "dot"), - TERMINAL_COLON(17, "colon"), - TERMINAL_SEMI(18, "semi"), - TERMINAL_LPAREN(19, "lparen"), - TERMINAL_INTO(20, "into"), - TERMINAL_LBRACE(21, "lbrace"), - TERMINAL_RBRACE(22, "rbrace"); + TERMINAL_LPAREN(16, "lparen"), + TERMINAL_SEMI(17, "semi"), + TERMINAL_FIRST_LINE(18, "first_line"), + TERMINAL_LSQUARE(19, "lsquare"), + TERMINAL_COLON(20, "colon"), + TERMINAL_ASSIGN(21, "assign"), + TERMINAL_AS(22, "as"), + TERMINAL_INPUT(23, "input"); private final int id; private final String string; TerminalId(int id, String string) { @@ -105,237 +107,246 @@ public CompositeTaskParser(SyntaxErrorFormatter syntaxErrorFormatter) { this.rules = new HashMap(); ArrayList list; String rule; + this.nonterminal_rules.put("_gen6", new ArrayList()); this.nonterminal_rules.put("step_name", new ArrayList()); - this.nonterminal_rules.put("_gen3", new ArrayList()); - this.nonterminal_rules.put("step_input", new ArrayList()); - this.nonterminal_rules.put("variable_member", new ArrayList()); - this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("_gen2", new ArrayList()); + this.nonterminal_rules.put("task_attr", new ArrayList()); this.nonterminal_rules.put("variable", new ArrayList()); + this.nonterminal_rules.put("step_output", new ArrayList()); + this.nonterminal_rules.put("_gen5", new ArrayList()); + this.nonterminal_rules.put("_gen4", new ArrayList()); + this.nonterminal_rules.put("step_output_list", new ArrayList()); this.nonterminal_rules.put("_gen10", new ArrayList()); - this.nonterminal_rules.put("step_output_location", new ArrayList()); + this.nonterminal_rules.put("step", new ArrayList()); this.nonterminal_rules.put("task_attr_value", new ArrayList()); - this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("wdl_entity", new ArrayList()); + this.nonterminal_rules.put("step_output_location", new ArrayList()); + this.nonterminal_rules.put("step_attr", new ArrayList()); + this.nonterminal_rules.put("_gen0", new ArrayList()); + this.nonterminal_rules.put("step_output_mode", new ArrayList()); + this.nonterminal_rules.put("_gen1", new ArrayList()); this.nonterminal_rules.put("wdl", new ArrayList()); + this.nonterminal_rules.put("composite_task_entity", new ArrayList()); + this.nonterminal_rules.put("step_input", new ArrayList()); + this.nonterminal_rules.put("_gen8", new ArrayList()); this.nonterminal_rules.put("step_input_list", new ArrayList()); - this.nonterminal_rules.put("wdl_entity", new ArrayList()); - this.nonterminal_rules.put("task_identifier", new ArrayList()); - this.nonterminal_rules.put("step_output", new ArrayList()); - this.nonterminal_rules.put("step", new ArrayList()); this.nonterminal_rules.put("_gen9", new ArrayList()); - this.nonterminal_rules.put("_gen8", new ArrayList()); - this.nonterminal_rules.put("composite_task", new ArrayList()); - this.nonterminal_rules.put("_gen2", new ArrayList()); - this.nonterminal_rules.put("step_output_list", new ArrayList()); - this.nonterminal_rules.put("task_attrs", new ArrayList()); - this.nonterminal_rules.put("task_attr", new ArrayList()); - this.nonterminal_rules.put("composite_task_entity", new ArrayList()); this.nonterminal_rules.put("for_loop", new ArrayList()); - this.nonterminal_rules.put("_gen1", new ArrayList()); - this.nonterminal_rules.put("_gen5", new ArrayList()); - this.nonterminal_rules.put("_gen6", new ArrayList()); - this.nonterminal_rules.put("_gen4", new ArrayList()); - this.nonterminal_rules.put("_gen0", new ArrayList()); - rule = "_gen4 := ε"; - this.nonterminal_rules.get("_gen4").add(rule); + this.nonterminal_rules.put("task_identifier", new ArrayList()); + this.nonterminal_rules.put("_gen3", new ArrayList()); + this.nonterminal_rules.put("task_attrs", new ArrayList()); + this.nonterminal_rules.put("composite_task", new ArrayList()); + this.nonterminal_rules.put("_gen7", new ArrayList()); + this.nonterminal_rules.put("variable_member", new ArrayList()); + rule = "_gen10 := variable_member"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(0), rule); - rule = "_gen0 := ε"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; + this.nonterminal_rules.get("step_output_list").add(rule); this.rules.put(new Integer(1), rule); - rule = "wdl_entity := composite_task"; - this.nonterminal_rules.get("wdl_entity").add(rule); + rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; + this.nonterminal_rules.get("step_input").add(rule); this.rules.put(new Integer(2), rule); - rule = "variable_member := 'dot' 'identifier' -> $1"; - this.nonterminal_rules.get("variable_member").add(rule); + rule = "_gen4 := task_attrs"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(3), rule); - rule = "step_output_location := 'into' variable -> OutputListAppend( var=$1 )"; - this.nonterminal_rules.get("step_output_location").add(rule); + rule = "wdl_entity := composite_task"; + this.nonterminal_rules.get("wdl_entity").add(rule); this.rules.put(new Integer(4), rule); rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( task=$1, name=$2, body=$4 )"; this.nonterminal_rules.get("step").add(rule); this.rules.put(new Integer(5), rule); - rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )"; - this.nonterminal_rules.get("task_identifier").add(rule); + rule = "step_output_location := 'as' variable -> OutputVariable( var=$1 )"; + this.nonterminal_rules.get("step_output_location").add(rule); this.rules.put(new Integer(6), rule); - rule = "_gen10 := variable_member"; - this.nonterminal_rules.get("_gen10").add(rule); + rule = "_gen5 := task_attr _gen5"; + this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(7), rule); - rule = "_gen10 := ε"; - this.nonterminal_rules.get("_gen10").add(rule); - this.rules.put(new Integer(8), rule); - rule = "composite_task_entity := composite_task"; - this.nonterminal_rules.get("composite_task_entity").add(rule); - this.rules.put(new Integer(9), rule); rule = "task_attr_value := 'identifier'"; this.nonterminal_rules.get("task_attr_value").add(rule); + this.rules.put(new Integer(8), rule); + rule = "_gen3 := step_attr _gen3"; + this.nonterminal_rules.get("_gen3").add(rule); + this.rules.put(new Integer(9), rule); + rule = "step_output := step_output_mode 'lparen' 'string' 'rparen' step_output_location -> StepOutput( mode=$0, expression=$2, var=$4 )"; + this.nonterminal_rules.get("step_output").add(rule); this.rules.put(new Integer(10), rule); rule = "_gen5 := ε"; this.nonterminal_rules.get("_gen5").add(rule); this.rules.put(new Integer(11), rule); - rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )"; - this.nonterminal_rules.get("variable").add(rule); + rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )"; + this.nonterminal_rules.get("task_identifier").add(rule); this.rules.put(new Integer(12), rule); - rule = "_gen8 := step_output _gen9"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "composite_task_entity := composite_task"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(13), rule); - rule = "_gen8 := ε"; - this.nonterminal_rules.get("_gen8").add(rule); + rule = "composite_task_entity := for_loop"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(14), rule); - rule = "step_output_location := 'as' variable -> OutputVariable( var=$1 )"; - this.nonterminal_rules.get("step_output_location").add(rule); + rule = "task_attr_value := 'number'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(15), rule); - rule = "wdl := _gen0"; - this.nonterminal_rules.get("wdl").add(rule); + rule = "_gen1 := composite_task_entity _gen1"; + this.nonterminal_rules.get("_gen1").add(rule); this.rules.put(new Integer(16), rule); - rule = "_gen9 := 'comma' step_output _gen9"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "step_name := 'as' 'identifier' -> $1"; + this.nonterminal_rules.get("step_name").add(rule); this.rules.put(new Integer(17), rule); - rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( key=$0, value=$2 )"; - this.nonterminal_rules.get("task_attr").add(rule); + rule = "_gen8 := step_output _gen9"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(18), rule); - rule = "_gen2 := step_name"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )"; + this.nonterminal_rules.get("variable").add(rule); this.rules.put(new Integer(19), rule); - rule = "task_attr_value := 'number'"; - this.nonterminal_rules.get("task_attr_value").add(rule); + rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; + this.nonterminal_rules.get("step_input_list").add(rule); this.rules.put(new Integer(20), rule); - rule = "_gen9 := ε"; - this.nonterminal_rules.get("_gen9").add(rule); + rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; + this.nonterminal_rules.get("task_attrs").add(rule); this.rules.put(new Integer(21), rule); - rule = "step_output := 'file' 'lparen' 'string' 'rparen' step_output_location -> StepFileOutput( file=$2, var=$4 )"; - this.nonterminal_rules.get("step_output").add(rule); + rule = "_gen9 := 'comma' step_output _gen9"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(22), rule); - rule = "_gen2 := ε"; - this.nonterminal_rules.get("_gen2").add(rule); + rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )"; + this.nonterminal_rules.get("for_loop").add(rule); this.rules.put(new Integer(23), rule); - rule = "_gen1 := ε"; - this.nonterminal_rules.get("_gen1").add(rule); + rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( key=$0, value=$2 )"; + this.nonterminal_rules.get("task_attr").add(rule); this.rules.put(new Integer(24), rule); - rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( name=$1, body=$3 )"; - this.nonterminal_rules.get("composite_task").add(rule); + rule = "wdl := _gen0"; + this.nonterminal_rules.get("wdl").add(rule); this.rules.put(new Integer(25), rule); - rule = "step_attr := step_input_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen9 := ε"; + this.nonterminal_rules.get("_gen9").add(rule); this.rules.put(new Integer(26), rule); - rule = "composite_task_entity := step"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "_gen0 := wdl_entity _gen0"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(27), rule); rule = "_gen6 := step_input _gen7"; this.nonterminal_rules.get("_gen6").add(rule); this.rules.put(new Integer(28), rule); - rule = "_gen4 := task_attrs"; - this.nonterminal_rules.get("_gen4").add(rule); + rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( name=$1, body=$3 )"; + this.nonterminal_rules.get("composite_task").add(rule); this.rules.put(new Integer(29), rule); - rule = "_gen0 := wdl_entity _gen0"; - this.nonterminal_rules.get("_gen0").add(rule); + rule = "_gen8 := ε"; + this.nonterminal_rules.get("_gen8").add(rule); this.rules.put(new Integer(30), rule); - rule = "composite_task_entity := for_loop"; - this.nonterminal_rules.get("composite_task_entity").add(rule); + rule = "step_output_location := 'into' variable -> OutputListAppend( var=$1 )"; + this.nonterminal_rules.get("step_output_location").add(rule); this.rules.put(new Integer(31), rule); - rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )"; - this.nonterminal_rules.get("step_output_list").add(rule); + rule = "variable_member := 'dot' 'identifier' -> $1"; + this.nonterminal_rules.get("variable_member").add(rule); this.rules.put(new Integer(32), rule); - rule = "_gen3 := ε"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "composite_task_entity := step"; + this.nonterminal_rules.get("composite_task_entity").add(rule); this.rules.put(new Integer(33), rule); rule = "_gen7 := ε"; this.nonterminal_rules.get("_gen7").add(rule); this.rules.put(new Integer(34), rule); - rule = "task_attr_value := 'string'"; - this.nonterminal_rules.get("task_attr_value").add(rule); - this.rules.put(new Integer(35), rule); rule = "_gen6 := ε"; this.nonterminal_rules.get("_gen6").add(rule); + this.rules.put(new Integer(35), rule); + rule = "step_output_mode := 'first_line'"; + this.nonterminal_rules.get("step_output_mode").add(rule); this.rules.put(new Integer(36), rule); - rule = "step_attr := step_output_list"; - this.nonterminal_rules.get("step_attr").add(rule); + rule = "_gen0 := ε"; + this.nonterminal_rules.get("_gen0").add(rule); this.rules.put(new Integer(37), rule); - rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )"; - this.nonterminal_rules.get("step_input").add(rule); + rule = "step_output_mode := 'file'"; + this.nonterminal_rules.get("step_output_mode").add(rule); this.rules.put(new Integer(38), rule); - rule = "_gen7 := 'comma' step_input _gen7"; - this.nonterminal_rules.get("_gen7").add(rule); + rule = "_gen2 := step_name"; + this.nonterminal_rules.get("_gen2").add(rule); this.rules.put(new Integer(39), rule); - rule = "step_name := 'as' 'identifier' -> $1"; - this.nonterminal_rules.get("step_name").add(rule); + rule = "_gen10 := ε"; + this.nonterminal_rules.get("_gen10").add(rule); this.rules.put(new Integer(40), rule); - rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )"; - this.nonterminal_rules.get("step_input_list").add(rule); + rule = "_gen3 := ε"; + this.nonterminal_rules.get("_gen3").add(rule); this.rules.put(new Integer(41), rule); - rule = "_gen5 := task_attr _gen5"; - this.nonterminal_rules.get("_gen5").add(rule); + rule = "_gen4 := ε"; + this.nonterminal_rules.get("_gen4").add(rule); this.rules.put(new Integer(42), rule); - rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )"; - this.nonterminal_rules.get("for_loop").add(rule); - this.rules.put(new Integer(43), rule); - rule = "_gen1 := composite_task_entity _gen1"; + rule = "_gen1 := ε"; this.nonterminal_rules.get("_gen1").add(rule); + this.rules.put(new Integer(43), rule); + rule = "task_attr_value := 'string'"; + this.nonterminal_rules.get("task_attr_value").add(rule); this.rules.put(new Integer(44), rule); - rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1"; - this.nonterminal_rules.get("task_attrs").add(rule); + rule = "step_attr := step_input_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(45), rule); - rule = "_gen3 := step_attr _gen3"; - this.nonterminal_rules.get("_gen3").add(rule); + rule = "step_attr := step_output_list"; + this.nonterminal_rules.get("step_attr").add(rule); this.rules.put(new Integer(46), rule); + rule = "_gen2 := ε"; + this.nonterminal_rules.get("_gen2").add(rule); + this.rules.put(new Integer(47), rule); + rule = "_gen7 := 'comma' step_input _gen7"; + this.nonterminal_rules.get("_gen7").add(rule); + this.rules.put(new Integer(48), rule); + this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); - this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE }); + this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT }); - this.first.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_AS, TerminalId.TERMINAL_INTO }); + this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING }); - this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_INTO, TerminalId.TERMINAL_AS }); + this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("step_output_mode", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE }); + this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP }); + this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE }); this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT }); - this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP }); this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA }); - this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE }); - this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT }); - this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR }); - this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP }); - this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); - this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); - this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER }); + this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE }); + this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); + this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA }); + this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT }); + this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); + this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); + this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("wdl", new TerminalId[] { }); - this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK }); - this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); - this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); + this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("step_output_mode", new TerminalId[] { TerminalId.TERMINAL_LPAREN }); + this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); + this.follow.put("wdl", new TerminalId[] { }); + this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE }); - this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_RBRACE, TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT }); + this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS }); + this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE }); - this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE }); - this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE }); - this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI }); - this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS }); - this.follow.put("_gen0", new TerminalId[] { }); + this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE }); + this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI }); + this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA }); } public TerminalMap getTerminalMap() { return new CompositeTaskTerminalMap(TerminalId.values()); @@ -352,23 +363,48 @@ public ParseTree parse(TokenStream tokens) throws SyntaxError { return tree; } private boolean isTerminal(TerminalId terminal) { - return (0 <= terminal.id() && terminal.id() <= 22); + return (0 <= terminal.id() && terminal.id() <= 23); } private boolean isNonTerminal(TerminalId terminal) { - return (23 <= terminal.id() && terminal.id() <= 52); + return (24 <= terminal.id() && terminal.id() <= 54); } private boolean isTerminal(int terminal) { - return (0 <= terminal && terminal <= 22); + return (0 <= terminal && terminal <= 23); } private boolean isNonTerminal(int terminal) { - return (23 <= terminal && terminal <= 52); + return (24 <= terminal && terminal <= 54); } - private ParseTree parse_step_name() throws SyntaxError { + private ParseTree parse__gen6() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[0][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(23, "step_name")); + ParseTree tree = new ParseTree( new NonTerminal(24, "_gen6")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 17) { + return tree; + } + } + if (current == null) { + return tree; + } + if (rule == 28) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input(); + tree.add( subtree); + subtree = this.parse__gen7(); + tree.add( subtree); + return tree; + } + return tree; + } + private ParseTree parse_step_name() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[1][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(25, "step_name")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -377,11 +413,11 @@ private ParseTree parse_step_name() throws SyntaxError { this.nonterminal_rules.get("step_name") )); } - if (rule == 40) { + if (rule == 17) { tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(40)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(17)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(40)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(17)); tree.add(next); return tree; } @@ -390,175 +426,149 @@ private ParseTree parse_step_name() throws SyntaxError { "step_name", current, Arrays.asList(this.first.get("step_name")), - this.rules.get(40) + this.rules.get(17) )); } - private ParseTree parse__gen3() throws SyntaxError { + private ParseTree parse__gen2() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[1][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(24, "_gen3")); - tree.setList("nlist"); + int rule = current != null ? this.table[2][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(26, "_gen2")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 22) { + if (current.getId() == 6) { return tree; } } if (current == null) { return tree; } - if (rule == 46) { + if (rule == 39) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_attr(); - tree.add( subtree); - subtree = this.parse__gen3(); + subtree = this.parse_step_name(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_input() throws SyntaxError { + private ParseTree parse_task_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; - int rule = current != null ? this.table[2][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(25, "step_input")); + int rule = current != null ? this.table[3][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(27, "task_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input", - Arrays.asList(this.first.get("step_input")), - this.nonterminal_rules.get("step_input") + "task_attr", + Arrays.asList(this.first.get("task_attr")), + this.nonterminal_rules.get("task_attr") )); } - if (rule == 38) { + if (rule == 24) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("parameter", 0); + parameters.put("key", 0); parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(38)); + tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(24)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(38)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(24)); tree.add(next); - subtree = this.parse_variable(); + subtree = this.parse_task_attr_value(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_input")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input", - current, - Arrays.asList(this.first.get("step_input")), - this.rules.get(38) - )); - } - private ParseTree parse_variable_member() throws SyntaxError { - Terminal current = this.tokens.current(); - Terminal next; - ParseTree subtree; - int rule = current != null ? this.table[3][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(26, "variable_member")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable_member", - Arrays.asList(this.first.get("variable_member")), - this.nonterminal_rules.get("variable_member") - )); - } - if (rule == 3) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(3)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(3)); - tree.add(next); - return tree; - } - List terminals = Arrays.asList(this.first.get("variable_member")); + List terminals = Arrays.asList(this.first.get("task_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable_member", + "task_attr", current, - Arrays.asList(this.first.get("variable_member")), - this.rules.get(3) + Arrays.asList(this.first.get("task_attr")), + this.rules.get(24) )); } - private ParseTree parse_step_attr() throws SyntaxError { + private ParseTree parse_variable() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[4][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(27, "step_attr")); + ParseTree tree = new ParseTree( new NonTerminal(28, "variable")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_attr", - Arrays.asList(this.first.get("step_attr")), - this.nonterminal_rules.get("step_attr") + "variable", + Arrays.asList(this.first.get("variable")), + this.nonterminal_rules.get("variable") )); } - if (rule == 26) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input_list(); - tree.add( subtree); - return tree; - } - else if (rule == 37) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output_list(); + if (rule == 19) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("member", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(19)); + tree.add(next); + subtree = this.parse__gen10(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_attr")); + List terminals = Arrays.asList(this.first.get("variable")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_attr", + "variable", current, - Arrays.asList(this.first.get("step_attr")), - this.rules.get(37) + Arrays.asList(this.first.get("variable")), + this.rules.get(19) )); } - private ParseTree parse_variable() throws SyntaxError { + private ParseTree parse_step_output() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[5][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(28, "variable")); + ParseTree tree = new ParseTree( new NonTerminal(29, "step_output")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "variable", - Arrays.asList(this.first.get("variable")), - this.nonterminal_rules.get("variable") + "step_output", + Arrays.asList(this.first.get("step_output")), + this.nonterminal_rules.get("step_output") )); } - if (rule == 12) { + if (rule == 10) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("member", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(12)); + parameters.put("mode", 0); + parameters.put("expression", 2); + parameters.put("var", 4); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutput", parameters)); + subtree = this.parse_step_output_mode(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(10)); tree.add(next); - subtree = this.parse__gen10(); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(10)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(10)); + tree.add(next); + subtree = this.parse_step_output_location(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("variable")); + List terminals = Arrays.asList(this.first.get("step_output")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "variable", + "step_output", current, - Arrays.asList(this.first.get("variable")), - this.rules.get(12) + Arrays.asList(this.first.get("step_output")), + this.rules.get(10) )); } - private ParseTree parse__gen10() throws SyntaxError { + private ParseTree parse__gen5() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[6][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(29, "_gen10")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(30, "_gen5")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 10 || current.getId() == 18) { + if (current.getId() == 0) { return tree; } } @@ -567,180 +577,176 @@ private ParseTree parse__gen10() throws SyntaxError { } if (rule == 7) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_variable_member(); + subtree = this.parse_task_attr(); + tree.add( subtree); + subtree = this.parse__gen5(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_step_output_location() throws SyntaxError { + private ParseTree parse__gen4() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[7][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(30, "step_output_location")); + ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4")); tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_location", - Arrays.asList(this.first.get("step_output_location")), - this.nonterminal_rules.get("step_output_location") - )); + if ( current != null ) { + if (current.getId() == 22) { + return tree; + } } - if (rule == 4) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("var", 1); - tree.setAstTransformation(new AstTransformNodeCreator("OutputListAppend", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INTO, "step_output_location", this.rules.get(4)); - tree.add(next); - subtree = this.parse_variable(); - tree.add( subtree); + if (current == null) { return tree; } - else if (rule == 15) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("var", 1); - tree.setAstTransformation(new AstTransformNodeCreator("OutputVariable", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output_location", this.rules.get(15)); - tree.add(next); - subtree = this.parse_variable(); + if (rule == 3) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_task_attrs(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_location")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_location", - current, - Arrays.asList(this.first.get("step_output_location")), - this.rules.get(15) - )); + return tree; } - private ParseTree parse_task_attr_value() throws SyntaxError { + private ParseTree parse_step_output_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[8][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(31, "task_attr_value")); + ParseTree tree = new ParseTree( new NonTerminal(32, "step_output_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr_value", - Arrays.asList(this.first.get("task_attr_value")), - this.nonterminal_rules.get("task_attr_value") + "step_output_list", + Arrays.asList(this.first.get("step_output_list")), + this.nonterminal_rules.get("step_output_list") )); } - if (rule == 10) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(10)); + if (rule == 1) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("outputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(1)); tree.add(next); - return tree; - } - else if (rule == 20) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(20)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(1)); tree.add(next); - return tree; - } - else if (rule == 35) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(35)); + subtree = this.parse__gen8(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(1)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr_value")); + List terminals = Arrays.asList(this.first.get("step_output_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr_value", + "step_output_list", current, - Arrays.asList(this.first.get("task_attr_value")), - this.rules.get(35) + Arrays.asList(this.first.get("step_output_list")), + this.rules.get(1) )); } - private ParseTree parse__gen7() throws SyntaxError { + private ParseTree parse__gen10() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[9][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(32, "_gen7")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(33, "_gen10")); + tree.setList(null); if ( current != null ) { - if (current.getId() == 18) { + if (current.getId() == 17 || current.getId() == 4) { return tree; } } if (current == null) { return tree; } - if (rule == 39) { + if (rule == 0) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(39)); - tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); + subtree = this.parse_variable_member(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_wdl() throws SyntaxError { + private ParseTree parse_step() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[10][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(33, "wdl")); + ParseTree tree = new ParseTree( new NonTerminal(34, "step")); tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step", + Arrays.asList(this.first.get("step")), + this.nonterminal_rules.get("step") + )); } - if (rule == 16) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse__gen0(); + if (rule == 5) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("task", 1); + parameters.put("name", 2); + parameters.put("body", 4); + tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(5)); + tree.add(next); + subtree = this.parse_task_identifier(); + tree.add( subtree); + subtree = this.parse__gen2(); + tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(5)); + tree.add(next); + subtree = this.parse__gen3(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(5)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("wdl")); + List terminals = Arrays.asList(this.first.get("step")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "wdl", + "step", current, - Arrays.asList(this.first.get("wdl")), - this.rules.get(16) + Arrays.asList(this.first.get("step")), + this.rules.get(5) )); } - private ParseTree parse_step_input_list() throws SyntaxError { + private ParseTree parse_task_attr_value() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[11][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(34, "step_input_list")); + ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr_value")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_input_list", - Arrays.asList(this.first.get("step_input_list")), - this.nonterminal_rules.get("step_input_list") + "task_attr_value", + Arrays.asList(this.first.get("task_attr_value")), + this.nonterminal_rules.get("task_attr_value") )); } - if (rule == 41) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("inputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(41)); + if (rule == 8) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(8)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(41)); + return tree; + } + else if (rule == 15) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(15)); tree.add(next); - subtree = this.parse__gen6(); - tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(41)); + return tree; + } + else if (rule == 44) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(44)); tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_input_list")); + List terminals = Arrays.asList(this.first.get("task_attr_value")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_input_list", + "task_attr_value", current, - Arrays.asList(this.first.get("step_input_list")), - this.rules.get(41) + Arrays.asList(this.first.get("task_attr_value")), + this.rules.get(44) )); } private ParseTree parse_wdl_entity() throws SyntaxError { @@ -748,7 +754,7 @@ private ParseTree parse_wdl_entity() throws SyntaxError { Terminal next; ParseTree subtree; int rule = current != null ? this.table[12][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(35, "wdl_entity")); + ParseTree tree = new ParseTree( new NonTerminal(36, "wdl_entity")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -757,7 +763,7 @@ private ParseTree parse_wdl_entity() throws SyntaxError { this.nonterminal_rules.get("wdl_entity") )); } - if (rule == 2) { + if (rule == 4) { tree.setAstTransformation(new AstTransformSubstitution(0)); subtree = this.parse_composite_task(); tree.add( subtree); @@ -768,387 +774,363 @@ private ParseTree parse_wdl_entity() throws SyntaxError { "wdl_entity", current, Arrays.asList(this.first.get("wdl_entity")), - this.rules.get(2) + this.rules.get(4) )); } - private ParseTree parse_task_identifier() throws SyntaxError { + private ParseTree parse_step_output_location() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[13][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(36, "task_identifier")); + ParseTree tree = new ParseTree( new NonTerminal(37, "step_output_location")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_identifier", - Arrays.asList(this.first.get("task_identifier")), - this.nonterminal_rules.get("task_identifier") + "step_output_location", + Arrays.asList(this.first.get("step_output_location")), + this.nonterminal_rules.get("step_output_location") )); } if (rule == 6) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 0); - parameters.put("attributes", 1); - tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(6)); + parameters.put("var", 1); + tree.setAstTransformation(new AstTransformNodeCreator("OutputVariable", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output_location", this.rules.get(6)); tree.add(next); - subtree = this.parse__gen4(); + subtree = this.parse_variable(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("task_identifier")); + else if (rule == 31) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("var", 1); + tree.setAstTransformation(new AstTransformNodeCreator("OutputListAppend", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INTO, "step_output_location", this.rules.get(31)); + tree.add(next); + subtree = this.parse_variable(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_output_location")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_identifier", + "step_output_location", current, - Arrays.asList(this.first.get("task_identifier")), - this.rules.get(6) + Arrays.asList(this.first.get("step_output_location")), + this.rules.get(31) )); } - private ParseTree parse_step_output() throws SyntaxError { + private ParseTree parse_step_attr() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[14][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(37, "step_output")); + ParseTree tree = new ParseTree( new NonTerminal(38, "step_attr")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output", - Arrays.asList(this.first.get("step_output")), - this.nonterminal_rules.get("step_output") + "step_attr", + Arrays.asList(this.first.get("step_attr")), + this.nonterminal_rules.get("step_attr") )); } - if (rule == 22) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("file", 2); - parameters.put("var", 4); - tree.setAstTransformation(new AstTransformNodeCreator("StepFileOutput", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output", this.rules.get(22)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(22)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(22)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(22)); - tree.add(next); - subtree = this.parse_step_output_location(); + if (rule == 45) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_input_list(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("step_output")); + else if (rule == 46) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output_list(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("step_attr")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output", + "step_attr", current, - Arrays.asList(this.first.get("step_output")), - this.rules.get(22) + Arrays.asList(this.first.get("step_attr")), + this.rules.get(46) )); } - private ParseTree parse_step() throws SyntaxError { + private ParseTree parse__gen0() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[15][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(38, "step")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(39, "_gen0")); + tree.setList("nlist"); + if ( current != null ) { + if (current.getId() == -1) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step", - Arrays.asList(this.first.get("step")), - this.nonterminal_rules.get("step") - )); + return tree; } - if (rule == 5) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("task", 1); - parameters.put("name", 2); - parameters.put("body", 4); - tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(5)); - tree.add(next); - subtree = this.parse_task_identifier(); - tree.add( subtree); - subtree = this.parse__gen2(); + if (rule == 27) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_wdl_entity(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(5)); - tree.add(next); - subtree = this.parse__gen3(); + subtree = this.parse__gen0(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(5)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step", - current, - Arrays.asList(this.first.get("step")), - this.rules.get(5) - )); + return tree; } - private ParseTree parse__gen9() throws SyntaxError { + private ParseTree parse_step_output_mode() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[16][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(39, "_gen9")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 18) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(40, "step_output_mode")); + tree.setList(null); if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "step_output_mode", + Arrays.asList(this.first.get("step_output_mode")), + this.nonterminal_rules.get("step_output_mode") + )); + } + if (rule == 36) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + next = this.tokens.expect(TerminalId.TERMINAL_FIRST_LINE, "step_output_mode", this.rules.get(36)); + tree.add(next); return tree; } - if (rule == 17) { + else if (rule == 38) { tree.setAstTransformation(new AstTransformSubstitution(0)); - next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(17)); + next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output_mode", this.rules.get(38)); tree.add(next); - tree.setListSeparator(next); - subtree = this.parse_step_output(); - tree.add( subtree); - subtree = this.parse__gen9(); - tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("step_output_mode")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "step_output_mode", + current, + Arrays.asList(this.first.get("step_output_mode")), + this.rules.get(38) + )); } - private ParseTree parse__gen8() throws SyntaxError { + private ParseTree parse__gen1() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[17][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(40, "_gen8")); - tree.setList("slist"); + ParseTree tree = new ParseTree( new NonTerminal(41, "_gen1")); + tree.setList("nlist"); if ( current != null ) { - if (current.getId() == 18) { + if (current.getId() == 1) { return tree; } } if (current == null) { return tree; } - if (rule == 13) { + if (rule == 16) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_output(); + subtree = this.parse_composite_task_entity(); tree.add( subtree); - subtree = this.parse__gen9(); + subtree = this.parse__gen1(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse_composite_task() throws SyntaxError { + private ParseTree parse_wdl() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[18][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(41, "composite_task")); + ParseTree tree = new ParseTree( new NonTerminal(42, "wdl")); tree.setList(null); if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task", - Arrays.asList(this.first.get("composite_task")), - this.nonterminal_rules.get("composite_task") - )); + return tree; } if (rule == 25) { - LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("name", 1); - parameters.put("body", 3); - tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(25)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(25)); - tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(25)); - tree.add(next); - subtree = this.parse__gen1(); + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse__gen0(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(25)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task")); + List terminals = Arrays.asList(this.first.get("wdl")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task", + "wdl", current, - Arrays.asList(this.first.get("composite_task")), + Arrays.asList(this.first.get("wdl")), this.rules.get(25) )); } - private ParseTree parse__gen2() throws SyntaxError { + private ParseTree parse_composite_task_entity() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[19][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(42, "_gen2")); + ParseTree tree = new ParseTree( new NonTerminal(43, "composite_task_entity")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 21) { - return tree; - } - } if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task_entity", + Arrays.asList(this.first.get("composite_task_entity")), + this.nonterminal_rules.get("composite_task_entity") + )); + } + if (rule == 13) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_composite_task(); + tree.add( subtree); return tree; } - if (rule == 19) { + else if (rule == 14) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_name(); + subtree = this.parse_for_loop(); tree.add( subtree); return tree; } - return tree; + else if (rule == 33) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step(); + tree.add( subtree); + return tree; + } + List terminals = Arrays.asList(this.first.get("composite_task_entity")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task_entity", + current, + Arrays.asList(this.first.get("composite_task_entity")), + this.rules.get(33) + )); } - private ParseTree parse_step_output_list() throws SyntaxError { + private ParseTree parse_step_input() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[20][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(43, "step_output_list")); + ParseTree tree = new ParseTree( new NonTerminal(44, "step_input")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "step_output_list", - Arrays.asList(this.first.get("step_output_list")), - this.nonterminal_rules.get("step_output_list") + "step_input", + Arrays.asList(this.first.get("step_input")), + this.nonterminal_rules.get("step_input") )); } - if (rule == 32) { + if (rule == 2) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("outputs", 2); - tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(32)); + parameters.put("parameter", 0); + parameters.put("value", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(2)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(32)); + next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(2)); tree.add(next); - subtree = this.parse__gen8(); + subtree = this.parse_variable(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(32)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("step_output_list")); + List terminals = Arrays.asList(this.first.get("step_input")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "step_output_list", + "step_input", current, - Arrays.asList(this.first.get("step_output_list")), - this.rules.get(32) + Arrays.asList(this.first.get("step_input")), + this.rules.get(2) )); } - private ParseTree parse_task_attrs() throws SyntaxError { + private ParseTree parse__gen8() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[21][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(44, "task_attrs")); - tree.setList(null); + ParseTree tree = new ParseTree( new NonTerminal(45, "_gen8")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 17) { + return tree; + } + } if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attrs", - Arrays.asList(this.first.get("task_attrs")), - this.nonterminal_rules.get("task_attrs") - )); + return tree; } - if (rule == 45) { - tree.setAstTransformation(new AstTransformSubstitution(1)); - next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(45)); - tree.add(next); - subtree = this.parse__gen5(); + if (rule == 18) { + tree.setAstTransformation(new AstTransformSubstitution(0)); + subtree = this.parse_step_output(); + tree.add( subtree); + subtree = this.parse__gen9(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(45)); - tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attrs")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attrs", - current, - Arrays.asList(this.first.get("task_attrs")), - this.rules.get(45) - )); + return tree; } - private ParseTree parse_task_attr() throws SyntaxError { + private ParseTree parse_step_input_list() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[22][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(45, "task_attr")); + ParseTree tree = new ParseTree( new NonTerminal(46, "step_input_list")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "task_attr", - Arrays.asList(this.first.get("task_attr")), - this.nonterminal_rules.get("task_attr") + "step_input_list", + Arrays.asList(this.first.get("step_input_list")), + this.nonterminal_rules.get("step_input_list") )); } - if (rule == 18) { + if (rule == 20) { LinkedHashMap parameters = new LinkedHashMap(); - parameters.put("key", 0); - parameters.put("value", 2); - tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(18)); + parameters.put("inputs", 2); + tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(20)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(18)); + next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(20)); tree.add(next); - subtree = this.parse_task_attr_value(); + subtree = this.parse__gen6(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(20)); + tree.add(next); return tree; } - List terminals = Arrays.asList(this.first.get("task_attr")); + List terminals = Arrays.asList(this.first.get("step_input_list")); throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "task_attr", + "step_input_list", current, - Arrays.asList(this.first.get("task_attr")), - this.rules.get(18) + Arrays.asList(this.first.get("step_input_list")), + this.rules.get(20) )); } - private ParseTree parse_composite_task_entity() throws SyntaxError { + private ParseTree parse__gen9() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[23][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(46, "composite_task_entity")); - tree.setList(null); - if (current == null) { - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( - "composite_task_entity", - Arrays.asList(this.first.get("composite_task_entity")), - this.nonterminal_rules.get("composite_task_entity") - )); + ParseTree tree = new ParseTree( new NonTerminal(47, "_gen9")); + tree.setList("slist"); + if ( current != null ) { + if (current.getId() == 17) { + return tree; + } } - if (rule == 9) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task(); - tree.add( subtree); + if (current == null) { return tree; } - else if (rule == 27) { + if (rule == 22) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(22)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_output(); tree.add( subtree); - return tree; - } - else if (rule == 31) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_for_loop(); + subtree = this.parse__gen9(); tree.add( subtree); return tree; } - List terminals = Arrays.asList(this.first.get("composite_task_entity")); - throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( - "composite_task_entity", - current, - Arrays.asList(this.first.get("composite_task_entity")), - this.rules.get(31) - )); + return tree; } private ParseTree parse_for_loop() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[24][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(47, "for_loop")); + ParseTree tree = new ParseTree( new NonTerminal(48, "for_loop")); tree.setList(null); if (current == null) { throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( @@ -1157,29 +1139,29 @@ private ParseTree parse_for_loop() throws SyntaxError { this.nonterminal_rules.get("for_loop") )); } - if (rule == 43) { + if (rule == 23) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("collection", 4); parameters.put("item", 2); parameters.put("body", 7); tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters)); - next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(23)); tree.add(next); - next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(23)); tree.add(next); subtree = this.parse__gen1(); tree.add( subtree); - next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(43)); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(23)); tree.add(next); return tree; } @@ -1188,40 +1170,48 @@ private ParseTree parse_for_loop() throws SyntaxError { "for_loop", current, Arrays.asList(this.first.get("for_loop")), - this.rules.get(43) + this.rules.get(23) )); } - private ParseTree parse__gen1() throws SyntaxError { + private ParseTree parse_task_identifier() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[25][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(48, "_gen1")); - tree.setList("nlist"); - if ( current != null ) { - if (current.getId() == 22) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(49, "task_identifier")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_identifier", + Arrays.asList(this.first.get("task_identifier")), + this.nonterminal_rules.get("task_identifier") + )); } - if (rule == 44) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_composite_task_entity(); - tree.add( subtree); - subtree = this.parse__gen1(); + if (rule == 12) { + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 0); + parameters.put("attributes", 1); + tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(12)); + tree.add(next); + subtree = this.parse__gen4(); tree.add( subtree); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("task_identifier")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_identifier", + current, + Arrays.asList(this.first.get("task_identifier")), + this.rules.get(12) + )); } - private ParseTree parse__gen5() throws SyntaxError { + private ParseTree parse__gen3() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[26][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(49, "_gen5")); + ParseTree tree = new ParseTree( new NonTerminal(50, "_gen3")); tree.setList("nlist"); if ( current != null ) { if (current.getId() == 1) { @@ -1231,87 +1221,143 @@ private ParseTree parse__gen5() throws SyntaxError { if (current == null) { return tree; } - if (rule == 42) { + if (rule == 9) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attr(); + subtree = this.parse_step_attr(); tree.add( subtree); - subtree = this.parse__gen5(); + subtree = this.parse__gen3(); tree.add( subtree); return tree; } return tree; } - private ParseTree parse__gen6() throws SyntaxError { + private ParseTree parse_task_attrs() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[27][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(50, "_gen6")); - tree.setList("slist"); - if ( current != null ) { - if (current.getId() == 18) { - return tree; - } - } + ParseTree tree = new ParseTree( new NonTerminal(51, "task_attrs")); + tree.setList(null); if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "task_attrs", + Arrays.asList(this.first.get("task_attrs")), + this.nonterminal_rules.get("task_attrs") + )); } - if (rule == 28) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_step_input(); - tree.add( subtree); - subtree = this.parse__gen7(); + if (rule == 21) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(21)); + tree.add(next); + subtree = this.parse__gen5(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(21)); + tree.add(next); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("task_attrs")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "task_attrs", + current, + Arrays.asList(this.first.get("task_attrs")), + this.rules.get(21) + )); } - private ParseTree parse__gen4() throws SyntaxError { + private ParseTree parse_composite_task() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[28][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(51, "_gen4")); + ParseTree tree = new ParseTree( new NonTerminal(52, "composite_task")); tree.setList(null); - if ( current != null ) { - if (current.getId() == 2) { - return tree; - } - } if (current == null) { - return tree; + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "composite_task", + Arrays.asList(this.first.get("composite_task")), + this.nonterminal_rules.get("composite_task") + )); } if (rule == 29) { - tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_task_attrs(); + LinkedHashMap parameters = new LinkedHashMap(); + parameters.put("name", 1); + parameters.put("body", 3); + tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters)); + next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(29)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(29)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(29)); + tree.add(next); + subtree = this.parse__gen1(); tree.add( subtree); + next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(29)); + tree.add(next); return tree; } - return tree; + List terminals = Arrays.asList(this.first.get("composite_task")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "composite_task", + current, + Arrays.asList(this.first.get("composite_task")), + this.rules.get(29) + )); } - private ParseTree parse__gen0() throws SyntaxError { + private ParseTree parse__gen7() throws SyntaxError { Terminal current = this.tokens.current(); Terminal next; ParseTree subtree; int rule = current != null ? this.table[29][current.getId()] : -1; - ParseTree tree = new ParseTree( new NonTerminal(52, "_gen0")); - tree.setList("nlist"); + ParseTree tree = new ParseTree( new NonTerminal(53, "_gen7")); + tree.setList("slist"); if ( current != null ) { - if (current.getId() == -1) { + if (current.getId() == 17) { return tree; } } if (current == null) { return tree; } - if (rule == 30) { + if (rule == 48) { tree.setAstTransformation(new AstTransformSubstitution(0)); - subtree = this.parse_wdl_entity(); + next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(48)); + tree.add(next); + tree.setListSeparator(next); + subtree = this.parse_step_input(); tree.add( subtree); - subtree = this.parse__gen0(); + subtree = this.parse__gen7(); tree.add( subtree); return tree; } return tree; } + private ParseTree parse_variable_member() throws SyntaxError { + Terminal current = this.tokens.current(); + Terminal next; + ParseTree subtree; + int rule = current != null ? this.table[30][current.getId()] : -1; + ParseTree tree = new ParseTree( new NonTerminal(54, "variable_member")); + tree.setList(null); + if (current == null) { + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof( + "variable_member", + Arrays.asList(this.first.get("variable_member")), + this.nonterminal_rules.get("variable_member") + )); + } + if (rule == 32) { + tree.setAstTransformation(new AstTransformSubstitution(1)); + next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(32)); + tree.add(next); + next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(32)); + tree.add(next); + return tree; + } + List terminals = Arrays.asList(this.first.get("variable_member")); + throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol( + "variable_member", + current, + Arrays.asList(this.first.get("variable_member")), + this.rules.get(32) + )); + } } From 8e46c306681c4922563eae3c6abb9357f57cc61e Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 15:54:15 -0400 Subject: [PATCH 126/140] Fixing the AST -> CompositeTask code for the new parser --- src/main/java/org/broadinstitute/compositetask/CompositeTask.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index 9cbd934..c1abb17 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -163,8 +163,9 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { AstList output_list = (AstList) entry_ast.getAttribute("outputs"); for ( AstNode output_node : output_list ) { Ast output = (Ast) output_node; - Terminal filepath = (Terminal) output.getAttribute("file"); + Terminal filepath = (Terminal) output.getAttribute("expression"); Ast step_output = (Ast) output.getAttribute("var"); + String mode = ((Terminal) output.getAttribute("mode")).getSourceString(); CompositeTaskVariable variable = ast_to_variable((Ast) step_output.getAttribute("var")); Terminal variable_terminal = (Terminal) ((Ast) ((Ast) output.getAttribute("var")).getAttribute("var")).getAttribute("name"); @@ -191,7 +192,7 @@ private CompositeTaskStep verify_step(Ast step) throws SyntaxError { this.output_files.put(filepath.getSourceString(), filepath); } - step_outputs.add( new CompositeTaskStepOutput("File", method, filepath.getSourceString(), variable) ); + step_outputs.add( new CompositeTaskStepOutput(mode, method, filepath.getSourceString(), variable) ); } } } From e03d84690e84ac44be93af6ce13321ded59c8bed Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 15:54:34 -0400 Subject: [PATCH 127/140] Fixing one test --- test-files/parsing/1/ast | 20 ++++++++++++-------- test-files/parsing/1/parsetree | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/test-files/parsing/1/ast b/test-files/parsing/1/ast index ab7c6a9..b372890 100644 --- a/test-files/parsing/1/ast +++ b/test-files/parsing/1/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -64,8 +65,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -109,8 +111,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -194,8 +197,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/1/parsetree b/test-files/parsing/1/parsetree index e27de1f..182cbd3 100644 --- a/test-files/parsing/1/parsetree +++ b/test-files/parsing/1/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -131,7 +133,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -216,7 +220,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -383,7 +389,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 148a994fe783193f8f500801e841d83ffb2d4cea Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 16:03:40 -0400 Subject: [PATCH 128/140] Fix unit test --- test-files/parsing/2/ast | 20 ++++++++++++-------- test-files/parsing/2/parsetree | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/test-files/parsing/2/ast b/test-files/parsing/2/ast index 2f78fbb..8b438df 100644 --- a/test-files/parsing/2/ast +++ b/test-files/parsing/2/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -64,8 +65,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -109,8 +111,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -284,8 +287,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/2/parsetree b/test-files/parsing/2/parsetree index b84accc..cf162f2 100644 --- a/test-files/parsing/2/parsetree +++ b/test-files/parsing/2/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -131,7 +133,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -216,7 +220,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -549,7 +555,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 332252f98a3290558fd7a10152de19f44326d603 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 16:03:56 -0400 Subject: [PATCH 129/140] Fix unit test --- test-files/parsing/5/ast | 25 +++++++++++++++---------- test-files/parsing/5/parsetree | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/test-files/parsing/5/ast b/test-files/parsing/5/ast index 6288f49..ee1f50e 100644 --- a/test-files/parsing/5/ast +++ b/test-files/parsing/5/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -42,8 +43,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -91,8 +93,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -142,8 +145,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -189,8 +193,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/5/parsetree b/test-files/parsing/5/parsetree index a011c3e..ee82871 100644 --- a/test-files/parsing/5/parsetree +++ b/test-files/parsing/5/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -91,7 +93,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -190,7 +194,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -295,7 +301,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -385,7 +393,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 83f7de057998181b1311f68d857e88f2da11c837 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Thu, 19 Sep 2013 16:08:21 -0400 Subject: [PATCH 130/140] Fix unit test --- test-files/parsing/12/ast | 15 +++++++++------ test-files/parsing/12/parsetree | 12 +++++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/test-files/parsing/12/ast b/test-files/parsing/12/ast index 8bf9f9a..8891a37 100644 --- a/test-files/parsing/12/ast +++ b/test-files/parsing/12/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -64,8 +65,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputListAppend: var=(Variable: name=identifier, @@ -109,8 +111,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputListAppend: var=(Variable: name=identifier, diff --git a/test-files/parsing/12/parsetree b/test-files/parsing/12/parsetree index e1fe201..cf99fa6 100644 --- a/test-files/parsing/12/parsetree +++ b/test-files/parsing/12/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -141,7 +143,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -236,7 +240,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 068964c8e1e4b21e3a806f89da3749ab7ad47f13 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 11:27:19 -0400 Subject: [PATCH 131/140] Fix unit test --- test-files/parsing/6/ast | 25 +++++++++++++++---------- test-files/parsing/6/parsetree | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/test-files/parsing/6/ast b/test-files/parsing/6/ast index 89c8cb8..5207f57 100644 --- a/test-files/parsing/6/ast +++ b/test-files/parsing/6/ast @@ -37,8 +37,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -66,8 +67,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -93,8 +95,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -164,8 +167,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -213,8 +217,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/6/parsetree b/test-files/parsing/6/parsetree index 94826f4..5a803a8 100644 --- a/test-files/parsing/6/parsetree +++ b/test-files/parsing/6/parsetree @@ -77,7 +77,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -137,7 +139,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -191,7 +195,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -333,7 +339,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -428,7 +436,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From ce7c3348c70c97fb0560fd518d086d0169b26bb0 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 11:28:21 -0400 Subject: [PATCH 132/140] Fix unit test --- test-files/parsing/8/ast | 10 ++++++---- test-files/parsing/8/parsetree | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/test-files/parsing/8/ast b/test-files/parsing/8/ast index f302ae3..bab60a6 100644 --- a/test-files/parsing/8/ast +++ b/test-files/parsing/8/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -75,8 +76,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/8/parsetree b/test-files/parsing/8/parsetree index b9e72b9..ad42ec3 100644 --- a/test-files/parsing/8/parsetree +++ b/test-files/parsing/8/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -152,7 +154,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 15e6fb693017cf7d04d243dd81e89b8ac08116fa Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 11:29:18 -0400 Subject: [PATCH 133/140] Fix unit test --- test-files/parsing/4/ast | 25 +++++++++++++++---------- test-files/parsing/4/parsetree | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/test-files/parsing/4/ast b/test-files/parsing/4/ast index f52d0bf..09cb4f4 100644 --- a/test-files/parsing/4/ast +++ b/test-files/parsing/4/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -42,8 +43,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -91,8 +93,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -136,8 +139,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -183,8 +187,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/4/parsetree b/test-files/parsing/4/parsetree index c8eb5bb..f222a2d 100644 --- a/test-files/parsing/4/parsetree +++ b/test-files/parsing/4/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -91,7 +93,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -190,7 +194,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -280,7 +286,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -371,7 +379,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From ee1547a89614add2bd8ffc4318b462457b92c1a3 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 11:30:10 -0400 Subject: [PATCH 134/140] Fix unit test --- test-files/parsing/11/ast | 20 ++++++++++++-------- test-files/parsing/11/parsetree | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/test-files/parsing/11/ast b/test-files/parsing/11/ast index 2e81e71..31c17f5 100644 --- a/test-files/parsing/11/ast +++ b/test-files/parsing/11/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -71,8 +72,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -123,8 +125,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -177,8 +180,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/11/parsetree b/test-files/parsing/11/parsetree index 553f314..8aec879 100644 --- a/test-files/parsing/11/parsetree +++ b/test-files/parsing/11/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -142,7 +144,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -238,7 +242,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -340,7 +346,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From ba54af37695f13f8ca97417be05952d3a4983d8b Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 11:34:20 -0400 Subject: [PATCH 135/140] Fix the remaining unit tests --- test-files/parsing/0/ast | 20 ++++++++++++-------- test-files/parsing/0/parsetree | 16 ++++++++++++---- test-files/parsing/14/ast | 35 +++++++++++++++++++++-------------- test-files/parsing/14/parsetree | 28 +++++++++++++++++++++------- test-files/parsing/17/ast | 10 ++++++---- test-files/parsing/17/parsetree | 8 ++++++-- test-files/parsing/7/ast | 5 +++-- test-files/parsing/7/parsetree | 4 +++- 8 files changed, 84 insertions(+), 42 deletions(-) diff --git a/test-files/parsing/0/ast b/test-files/parsing/0/ast index 2e81e71..31c17f5 100644 --- a/test-files/parsing/0/ast +++ b/test-files/parsing/0/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -71,8 +72,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -123,8 +125,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -177,8 +180,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/0/parsetree b/test-files/parsing/0/parsetree index 553f314..8aec879 100644 --- a/test-files/parsing/0/parsetree +++ b/test-files/parsing/0/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -142,7 +144,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -238,7 +242,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -340,7 +346,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, diff --git a/test-files/parsing/14/ast b/test-files/parsing/14/ast index 15565dd..6a9387d 100644 --- a/test-files/parsing/14/ast +++ b/test-files/parsing/14/ast @@ -15,8 +15,9 @@ body=[ (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -24,8 +25,9 @@ ) ) ), - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -33,8 +35,9 @@ ) ) ), - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -42,8 +45,9 @@ ) ) ), - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -94,8 +98,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -103,8 +108,9 @@ ) ) ), - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -169,8 +175,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/14/parsetree b/test-files/parsing/14/parsetree index f60e872..48ff5ed 100644 --- a/test-files/parsing/14/parsetree +++ b/test-files/parsing/14/parsetree @@ -37,7 +37,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -52,7 +54,9 @@ (_gen9: comma, (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -67,7 +71,9 @@ (_gen9: comma, (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -82,7 +88,9 @@ (_gen9: comma, (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -180,7 +188,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -195,7 +205,9 @@ (_gen9: comma, (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -319,7 +331,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, diff --git a/test-files/parsing/17/ast b/test-files/parsing/17/ast index 5a80e26..7978b86 100644 --- a/test-files/parsing/17/ast +++ b/test-files/parsing/17/ast @@ -26,8 +26,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, @@ -75,8 +76,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputListAppend: var=(Variable: name=identifier, diff --git a/test-files/parsing/17/parsetree b/test-files/parsing/17/parsetree index 886bcd1..3881773 100644 --- a/test-files/parsing/17/parsetree +++ b/test-files/parsing/17/parsetree @@ -56,7 +56,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, @@ -156,7 +158,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, diff --git a/test-files/parsing/7/ast b/test-files/parsing/7/ast index 9bcd3f0..2d2f32d 100644 --- a/test-files/parsing/7/ast +++ b/test-files/parsing/7/ast @@ -44,8 +44,9 @@ ), (StepOutputList: outputs=[ - (StepFileOutput: - file=string, + (StepOutput: + mode=file, + expression=string, var=(OutputVariable: var=(Variable: name=identifier, diff --git a/test-files/parsing/7/parsetree b/test-files/parsing/7/parsetree index bbf5f6b..7e33866 100644 --- a/test-files/parsing/7/parsetree +++ b/test-files/parsing/7/parsetree @@ -93,7 +93,9 @@ colon, (_gen8: (step_output: - file, + (step_output_mode: + file + ), lparen, string, rparen, From 207bf0ec740efcefbde7bd664169d53e40d02103 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 12:29:46 -0400 Subject: [PATCH 136/140] Adding unit tests for the new FirstLine() directive --- test-files/parsing/18/ast | 96 +++++++++++++++++++ test-files/parsing/18/formatted | 12 +++ test-files/parsing/18/graph | 42 +++++++++ test-files/parsing/18/parsetree | 199 +++++++++++++++++++++++++++++++++++++++ test-files/parsing/18/source.wdl | 11 +++ test-files/parsing/18/tokens | 68 +++++++++++++ 6 files changed, 428 insertions(+) create mode 100644 test-files/parsing/18/ast create mode 100644 test-files/parsing/18/formatted create mode 100644 test-files/parsing/18/graph create mode 100644 test-files/parsing/18/parsetree create mode 100644 test-files/parsing/18/source.wdl create mode 100644 test-files/parsing/18/tokens diff --git a/test-files/parsing/18/ast b/test-files/parsing/18/ast new file mode 100644 index 0000000..9a866e0 --- /dev/null +++ b/test-files/parsing/18/ast @@ -0,0 +1,96 @@ +(CompositeTask: + name=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=string + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepOutput: + mode=first_line, + expression=string, + var=(OutputVariable: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ), + (ForLoop: + collection=identifier, + item=identifier, + body=[ + (Step: + task=(Task: + name=identifier, + attributes=[ + (TaskAttribute: + key=identifier, + value=string + ) + ] + ), + name=None, + body=[ + (StepInputList: + inputs=[ + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=None + ) + ), + (StepInput: + parameter=identifier, + value=(Variable: + name=identifier, + member=identifier + ) + ) + ] + ), + (StepOutputList: + outputs=[ + (StepOutput: + mode=file, + expression=string, + var=(OutputListAppend: + var=(Variable: + name=identifier, + member=None + ) + ) + ) + ] + ) + ] + ) + ] + ) + ] +) \ No newline at end of file diff --git a/test-files/parsing/18/formatted b/test-files/parsing/18/formatted new file mode 100644 index 0000000..d615938 --- /dev/null +++ b/test-files/parsing/18/formatted @@ -0,0 +1,12 @@ +composite_task x { + step a[version="1.5.6"] { + input: in0=global; + output: FirstLine("a_out.txt") as a_out; + } + for ( b in c ) { + step d[version="1.0.2"] { + input: in0=a_out, in1=b.x; + output: File("d_out.txt") as d_out; + } + } +} diff --git a/test-files/parsing/18/graph b/test-files/parsing/18/graph new file mode 100644 index 0000000..1ca6bdb --- /dev/null +++ b/test-files/parsing/18/graph @@ -0,0 +1,42 @@ +VERTICIES +--------- +[CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] +[Step: name=a] +[Step: name=d] +[Variable: name=a_out] +[Variable: name=b, member=x] +[Variable: name=b] +[Variable: name=c] +[Variable: name=d_out] +[Variable: name=global] + +EDGES +----- +[Edge + from: [CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] + to: [Variable: name=b] +] +[Edge + from: [Step: name=a] + to: [Variable: name=a_out] +] +[Edge + from: [Step: name=d] + to: [Variable: name=d_out] +] +[Edge + from: [Variable: name=a_out] + to: [Step: name=d] +] +[Edge + from: [Variable: name=b, member=x] + to: [Step: name=d] +] +[Edge + from: [Variable: name=c] + to: [CompositeTaskForScope: collection=[Variable: name=c], var=[Variable: name=b], # nodes=1] +] +[Edge + from: [Variable: name=global] + to: [Step: name=a] +] diff --git a/test-files/parsing/18/parsetree b/test-files/parsing/18/parsetree new file mode 100644 index 0000000..df73aa8 --- /dev/null +++ b/test-files/parsing/18/parsetree @@ -0,0 +1,199 @@ +(wdl: + (_gen0: + (wdl_entity: + (composite_task: + composite_task, + identifier, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + string + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + (step_output_mode: + first_line + ), + lparen, + string, + rparen, + (step_output_location: + as, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: + (composite_task_entity: + (for_loop: + for, + lparen, + identifier, + in, + identifier, + rparen, + lbrace, + (_gen1: + (composite_task_entity: + (step: + step, + (task_identifier: + identifier, + (_gen4: + (task_attrs: + lsquare, + (_gen5: + (task_attr: + identifier, + assign, + (task_attr_value: + string + ) + ), + (_gen5: ) + ), + rsquare + ) + ) + ), + (_gen2: ), + lbrace, + (_gen3: + (step_attr: + (step_input_list: + input, + colon, + (_gen6: + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: ) + ) + ), + (_gen7: + comma, + (step_input: + identifier, + assign, + (variable: + identifier, + (_gen10: + (variable_member: + dot, + identifier + ) + ) + ) + ), + (_gen7: ) + ) + ), + semi + ) + ), + (_gen3: + (step_attr: + (step_output_list: + output, + colon, + (_gen8: + (step_output: + (step_output_mode: + file + ), + lparen, + string, + rparen, + (step_output_location: + into, + (variable: + identifier, + (_gen10: ) + ) + ) + ), + (_gen9: ) + ), + semi + ) + ), + (_gen3: ) + ) + ), + rbrace + ) + ), + (_gen1: ) + ), + rbrace + ) + ), + (_gen1: ) + ) + ), + rbrace + ) + ), + (_gen0: ) + ) +) \ No newline at end of file diff --git a/test-files/parsing/18/source.wdl b/test-files/parsing/18/source.wdl new file mode 100644 index 0000000..d85e951 --- /dev/null +++ b/test-files/parsing/18/source.wdl @@ -0,0 +1,11 @@ +composite_task x { + step a[version="1.5.6"] { + input: in0=global; + output: FirstLine("a_out.txt") as a_out; + } + for ( b in c ) { + step d[version="1.0.2"] { + input: in0=a_out, in1=b.x; output: File("d_out.txt") into d_out; + } + } +} diff --git a/test-files/parsing/18/tokens b/test-files/parsing/18/tokens new file mode 100644 index 0000000..cfff2f3 --- /dev/null +++ b/test-files/parsing/18/tokens @@ -0,0 +1,68 @@ +[ + {"terminal": "composite_task", "line": 1, "col": 1, "resource": "test-files/parsing/18/source.wdl", "source_string": "Y29tcG9zaXRlX3Rhc2s="}, + {"terminal": "identifier", "line": 1, "col": 16, "resource": "test-files/parsing/18/source.wdl", "source_string": "eA=="}, + {"terminal": "lbrace", "line": 1, "col": 18, "resource": "test-files/parsing/18/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 2, "col": 3, "resource": "test-files/parsing/18/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 2, "col": 8, "resource": "test-files/parsing/18/source.wdl", "source_string": "YQ=="}, + {"terminal": "lsquare", "line": 2, "col": 9, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 2, "col": 10, "resource": "test-files/parsing/18/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 2, "col": 17, "resource": "test-files/parsing/18/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 2, "col": 18, "resource": "test-files/parsing/18/source.wdl", "source_string": "IjEuNS42Ig=="}, + {"terminal": "rsquare", "line": 2, "col": 25, "resource": "test-files/parsing/18/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 2, "col": 27, "resource": "test-files/parsing/18/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 3, "col": 5, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 3, "col": 10, "resource": "test-files/parsing/18/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 3, "col": 12, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 3, "col": 15, "resource": "test-files/parsing/18/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 3, "col": 16, "resource": "test-files/parsing/18/source.wdl", "source_string": "Z2xvYmFs"}, + {"terminal": "semi", "line": 3, "col": 22, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 4, "col": 5, "resource": "test-files/parsing/18/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 4, "col": 11, "resource": "test-files/parsing/18/source.wdl", "source_string": "Og=="}, + {"terminal": "first_line", "line": 4, "col": 13, "resource": "test-files/parsing/18/source.wdl", "source_string": "Rmlyc3RMaW5l"}, + {"terminal": "lparen", "line": 4, "col": 22, "resource": "test-files/parsing/18/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 4, "col": 23, "resource": "test-files/parsing/18/source.wdl", "source_string": "ImFfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 4, "col": 34, "resource": "test-files/parsing/18/source.wdl", "source_string": "KQ=="}, + {"terminal": "as", "line": 4, "col": 36, "resource": "test-files/parsing/18/source.wdl", "source_string": "YXM="}, + {"terminal": "identifier", "line": 4, "col": 39, "resource": "test-files/parsing/18/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "semi", "line": 4, "col": 44, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 5, "col": 3, "resource": "test-files/parsing/18/source.wdl", "source_string": "fQ=="}, + {"terminal": "for", "line": 6, "col": 3, "resource": "test-files/parsing/18/source.wdl", "source_string": "Zm9y"}, + {"terminal": "lparen", "line": 6, "col": 7, "resource": "test-files/parsing/18/source.wdl", "source_string": "KA=="}, + {"terminal": "identifier", "line": 6, "col": 9, "resource": "test-files/parsing/18/source.wdl", "source_string": "Yg=="}, + {"terminal": "in", "line": 6, "col": 11, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW4="}, + {"terminal": "identifier", "line": 6, "col": 14, "resource": "test-files/parsing/18/source.wdl", "source_string": "Yw=="}, + {"terminal": "rparen", "line": 6, "col": 16, "resource": "test-files/parsing/18/source.wdl", "source_string": "KQ=="}, + {"terminal": "lbrace", "line": 6, "col": 18, "resource": "test-files/parsing/18/source.wdl", "source_string": "ew=="}, + {"terminal": "step", "line": 7, "col": 5, "resource": "test-files/parsing/18/source.wdl", "source_string": "c3RlcA=="}, + {"terminal": "identifier", "line": 7, "col": 10, "resource": "test-files/parsing/18/source.wdl", "source_string": "ZA=="}, + {"terminal": "lsquare", "line": 7, "col": 11, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ww=="}, + {"terminal": "identifier", "line": 7, "col": 12, "resource": "test-files/parsing/18/source.wdl", "source_string": "dmVyc2lvbg=="}, + {"terminal": "assign", "line": 7, "col": 19, "resource": "test-files/parsing/18/source.wdl", "source_string": "PQ=="}, + {"terminal": "string", "line": 7, "col": 20, "resource": "test-files/parsing/18/source.wdl", "source_string": "IjEuMC4yIg=="}, + {"terminal": "rsquare", "line": 7, "col": 27, "resource": "test-files/parsing/18/source.wdl", "source_string": "XQ=="}, + {"terminal": "lbrace", "line": 7, "col": 29, "resource": "test-files/parsing/18/source.wdl", "source_string": "ew=="}, + {"terminal": "input", "line": 8, "col": 7, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW5wdXQ="}, + {"terminal": "colon", "line": 8, "col": 12, "resource": "test-files/parsing/18/source.wdl", "source_string": "Og=="}, + {"terminal": "identifier", "line": 8, "col": 14, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW4w"}, + {"terminal": "assign", "line": 8, "col": 17, "resource": "test-files/parsing/18/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 8, "col": 18, "resource": "test-files/parsing/18/source.wdl", "source_string": "YV9vdXQ="}, + {"terminal": "comma", "line": 8, "col": 23, "resource": "test-files/parsing/18/source.wdl", "source_string": "LA=="}, + {"terminal": "identifier", "line": 8, "col": 25, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW4x"}, + {"terminal": "assign", "line": 8, "col": 28, "resource": "test-files/parsing/18/source.wdl", "source_string": "PQ=="}, + {"terminal": "identifier", "line": 8, "col": 29, "resource": "test-files/parsing/18/source.wdl", "source_string": "Yg=="}, + {"terminal": "dot", "line": 8, "col": 30, "resource": "test-files/parsing/18/source.wdl", "source_string": "Lg=="}, + {"terminal": "identifier", "line": 8, "col": 31, "resource": "test-files/parsing/18/source.wdl", "source_string": "eA=="}, + {"terminal": "semi", "line": 8, "col": 32, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ow=="}, + {"terminal": "output", "line": 8, "col": 34, "resource": "test-files/parsing/18/source.wdl", "source_string": "b3V0cHV0"}, + {"terminal": "colon", "line": 8, "col": 40, "resource": "test-files/parsing/18/source.wdl", "source_string": "Og=="}, + {"terminal": "file", "line": 8, "col": 42, "resource": "test-files/parsing/18/source.wdl", "source_string": "RmlsZQ=="}, + {"terminal": "lparen", "line": 8, "col": 46, "resource": "test-files/parsing/18/source.wdl", "source_string": "KA=="}, + {"terminal": "string", "line": 8, "col": 47, "resource": "test-files/parsing/18/source.wdl", "source_string": "ImRfb3V0LnR4dCI="}, + {"terminal": "rparen", "line": 8, "col": 58, "resource": "test-files/parsing/18/source.wdl", "source_string": "KQ=="}, + {"terminal": "into", "line": 8, "col": 60, "resource": "test-files/parsing/18/source.wdl", "source_string": "aW50bw=="}, + {"terminal": "identifier", "line": 8, "col": 65, "resource": "test-files/parsing/18/source.wdl", "source_string": "ZF9vdXQ="}, + {"terminal": "semi", "line": 8, "col": 70, "resource": "test-files/parsing/18/source.wdl", "source_string": "Ow=="}, + {"terminal": "rbrace", "line": 9, "col": 5, "resource": "test-files/parsing/18/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 10, "col": 3, "resource": "test-files/parsing/18/source.wdl", "source_string": "fQ=="}, + {"terminal": "rbrace", "line": 11, "col": 1, "resource": "test-files/parsing/18/source.wdl", "source_string": "fQ=="} +] From 2fe0e2d3215ca07948ccfb53399a185b78f52755 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 15:01:55 -0400 Subject: [PATCH 137/140] Adding some more tests --- .../org/broadinstitute/compositetask/ApiTest.java | 66 ++++++++++++++++++++++ test-files/api/0.wdl | 15 +++++ 2 files changed, 81 insertions(+) create mode 100644 src/test/java/org/broadinstitute/compositetask/ApiTest.java create mode 100644 test-files/api/0.wdl diff --git a/src/test/java/org/broadinstitute/compositetask/ApiTest.java b/src/test/java/org/broadinstitute/compositetask/ApiTest.java new file mode 100644 index 0000000..d9e1874 --- /dev/null +++ b/src/test/java/org/broadinstitute/compositetask/ApiTest.java @@ -0,0 +1,66 @@ +package org.broadinstitute.compositetask; + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeClass; +import org.testng.Assert; + +import java.io.File; +import java.io.IOException; +import java.util.Set; + +import org.broadinstitute.parser.SyntaxError; + +import org.broadinstitute.compositetask.CompositeTask; + +public class ApiTest +{ + private CompositeTask task; + + @BeforeClass + private void createCompositeTaskObject() { + try { + File source = new File("test-files/api/0.wdl"); + String relative = new File(".").toURI().relativize(source.toURI()).getPath(); + this.task = new CompositeTask(source, relative); + } catch(IOException error) { + Assert.fail("IOException reading file: " + error); + } catch(SyntaxError error) { + Assert.fail("Not expecting syntax error: " + error); + } + } + + @Test + public void testGetNodesMethodReturnsTheRightNumberOfNodes() { + Set nodes = this.task.getNodes(); + Assert.assertEquals(nodes.size(), 2, "Expecting 2 nodes, found " + nodes.size()); + } + + @Test + public void testGetNodesMethodReturnsASingleTopLevelStepNode() { + Set nodes = this.task.getNodes(); + boolean found = false; + for ( CompositeTaskNode node : nodes ) { + if ( node instanceof CompositeTaskStep ) { + found = true; + CompositeTaskStep step = (CompositeTaskStep) node; + Assert.assertEquals(step.getName(), "atask", "Expecting one step with name 'atask'"); + } + } + Assert.assertTrue(found, "Expected one top-level step in the composite task, didn't find any"); + } + + @Test + public void testGetNodesMethodReturnsASingleTopLevelForLoopNode() { + Set nodes = this.task.getNodes(); + boolean found = false; + for ( CompositeTaskNode node : nodes ) { + if ( node instanceof CompositeTaskForLoop ) { + found = true; + CompositeTaskForLoop loop = (CompositeTaskForLoop) node; + Assert.assertEquals(loop.getCollection().getName(), "foobar", "Expecting one loop with a collection called 'foobar'"); + Assert.assertEquals(loop.getVariable().getName(), "item", "Expecting one loop with a variable called 'item'"); + } + } + Assert.assertTrue(found, "Expected one top-level loop in the composite task, didn't find any"); + } +} diff --git a/test-files/api/0.wdl b/test-files/api/0.wdl new file mode 100644 index 0000000..25880be --- /dev/null +++ b/test-files/api/0.wdl @@ -0,0 +1,15 @@ +composite_task foo { + + step atask[version=0] { + output: File("foo.txt") as x, + FirstLine("bar.txt") as y; + } + + for ( item in foobar ) { + step btask[version=0] { + input: p0=x, p1=item, p2=GLOBAL; + output: File("baz.txt") as z; + } + } + +} From 8dacc4e58146f50611161ebd81d39e3e0a4e66b5 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 15:18:47 -0400 Subject: [PATCH 138/140] A much more sane way to phrase these tests... --- .../org/broadinstitute/compositetask/ApiTest.java | 27 ++++++---------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/test/java/org/broadinstitute/compositetask/ApiTest.java b/src/test/java/org/broadinstitute/compositetask/ApiTest.java index d9e1874..5804e60 100644 --- a/src/test/java/org/broadinstitute/compositetask/ApiTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ApiTest.java @@ -37,30 +37,17 @@ public void testGetNodesMethodReturnsTheRightNumberOfNodes() { @Test public void testGetNodesMethodReturnsASingleTopLevelStepNode() { - Set nodes = this.task.getNodes(); - boolean found = false; - for ( CompositeTaskNode node : nodes ) { - if ( node instanceof CompositeTaskStep ) { - found = true; - CompositeTaskStep step = (CompositeTaskStep) node; - Assert.assertEquals(step.getName(), "atask", "Expecting one step with name 'atask'"); - } - } - Assert.assertTrue(found, "Expected one top-level step in the composite task, didn't find any"); + CompositeTaskStep step = this.task.getStep("atask"); + Assert.assertNotNull(step, "Expected one step with name 'atask'"); + Assert.assertEquals(step.getName(), "atask", "Expecting one step with name 'atask'"); } @Test public void testGetNodesMethodReturnsASingleTopLevelForLoopNode() { Set nodes = this.task.getNodes(); - boolean found = false; - for ( CompositeTaskNode node : nodes ) { - if ( node instanceof CompositeTaskForLoop ) { - found = true; - CompositeTaskForLoop loop = (CompositeTaskForLoop) node; - Assert.assertEquals(loop.getCollection().getName(), "foobar", "Expecting one loop with a collection called 'foobar'"); - Assert.assertEquals(loop.getVariable().getName(), "item", "Expecting one loop with a variable called 'item'"); - } - } - Assert.assertTrue(found, "Expected one top-level loop in the composite task, didn't find any"); + CompositeTaskStep innerStep = this.task.getStep("btask"); + CompositeTaskForLoop loop = (CompositeTaskForLoop) innerStep.getParent(); + Assert.assertEquals(loop.getCollection().getName(), "foobar", "Expecting one loop with a collection called 'foobar'"); + Assert.assertEquals(loop.getVariable().getName(), "item", "Expecting one loop with a variable called 'item'"); } } From d8c4784fb450c95b624b78010cc19993df25e6f8 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Fri, 20 Sep 2013 22:22:34 -0400 Subject: [PATCH 139/140] Add more tests, refactor existing tests --- .../org/broadinstitute/compositetask/ApiTest.java | 40 +++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/broadinstitute/compositetask/ApiTest.java b/src/test/java/org/broadinstitute/compositetask/ApiTest.java index 5804e60..133ede6 100644 --- a/src/test/java/org/broadinstitute/compositetask/ApiTest.java +++ b/src/test/java/org/broadinstitute/compositetask/ApiTest.java @@ -31,22 +31,54 @@ private void createCompositeTaskObject() { @Test public void testGetNodesMethodReturnsTheRightNumberOfNodes() { - Set nodes = this.task.getNodes(); - Assert.assertEquals(nodes.size(), 2, "Expecting 2 nodes, found " + nodes.size()); + Assert.assertEquals(this.task.getNodes().size(), 2, "Expecting 2 nodes, found " + this.task.getNodes().size()); } @Test - public void testGetNodesMethodReturnsASingleTopLevelStepNode() { + public void testGetStepMethodReturnsTheCorrectTopLevelStep() { CompositeTaskStep step = this.task.getStep("atask"); Assert.assertNotNull(step, "Expected one step with name 'atask'"); Assert.assertEquals(step.getName(), "atask", "Expecting one step with name 'atask'"); + Assert.assertEquals(step.getParent(), this.task, "Expecting the parent of 'atask' step to be the composite task"); + } + + @Test + public void testTopLevelStepHasCorrectOutputMappingsToVariableX() { + CompositeTaskStep step = this.task.getStep("atask"); + boolean found = false; + for ( CompositeTaskStepOutput output : step.getOutputs() ) { + if ( output.getVariable().getName().equals("x") ) { + found = true; + Assert.assertEquals(output.getType(), "File", "Expected the variable 'x' to be a File mapping"); + Assert.assertEquals(output.getMethod(), "assign", "Expected the mapping method to be 'assign'"); + Assert.assertEquals(output.getPath(), "foo.txt", "Expected the output file path to be 'foo.txt'"); + } + } + if ( !found ) Assert.fail("Expected to find one output to 'atask' to variable 'x'"); + } + + @Test + public void testTopLevelStepHasCorrectOutputMappingsToVariableY() { + CompositeTaskStep step = this.task.getStep("atask"); + boolean found = false; + for ( CompositeTaskStepOutput output : step.getOutputs() ) { + if ( output.getVariable().getName().equals("y") ) { + found = true; + Assert.assertEquals(output.getType(), "FirstLine", "Expected the variable 'y' to be a File mapping"); + Assert.assertEquals(output.getMethod(), "assign", "Expected the mapping method to be 'assign'"); + Assert.assertEquals(output.getPath(), "bar.txt", "Expected the output file path to be 'bar.txt'"); + } + } + if ( !found ) Assert.fail("Expected to find one output to 'atask' to variable 'y'"); } @Test - public void testGetNodesMethodReturnsASingleTopLevelForLoopNode() { + public void testSingleTopLevelForLoopExistsWithSubTask() { Set nodes = this.task.getNodes(); CompositeTaskStep innerStep = this.task.getStep("btask"); + Assert.assertNotNull(innerStep, "Expected a step with name 'btask' to exist"); CompositeTaskForLoop loop = (CompositeTaskForLoop) innerStep.getParent(); + Assert.assertEquals(loop.getParent(), this.task, "Expected the loop's parent node to be the composite task"); Assert.assertEquals(loop.getCollection().getName(), "foobar", "Expecting one loop with a collection called 'foobar'"); Assert.assertEquals(loop.getVariable().getName(), "item", "Expecting one loop with a variable called 'item'"); } From 94f8e0411a0af55fcd941b1ad245b3d8a57208d6 Mon Sep 17 00:00:00 2001 From: Scott Frazer Date: Mon, 23 Sep 2013 15:24:36 -0400 Subject: [PATCH 140/140] Version bump --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e65600f..259f3ad 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ org.broadinstitute.compositetask Wdl jar - 0.0.1 + 0.0.2 Wdl http://github.com/broadinstitute/wdl

    23. NOTE jvs 1-Jan-2008: This is an internal data structure for use in - * algorithms. For returning paths to callers, use the public {@link GraphPath} - * interface instead. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -abstract class AbstractPathElement -{ - //~ Instance fields -------------------------------------------------------- - - /** - * Number of hops of the path. - */ - protected int nHops; - - /** - * Edge reaching the target vertex of the path. - */ - protected E prevEdge; - - /** - * Previous path element. - */ - protected AbstractPathElement prevPathElement; - - /** - * Target vertex. - */ - private V vertex; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a path element by concatenation of an edge to a path element. - * - * @param pathElement - * @param edge edge reaching the end vertex of the path element created. - */ - protected AbstractPathElement( - Graph graph, - AbstractPathElement pathElement, - E edge) - { - this.vertex = - Graphs.getOppositeVertex( - graph, - edge, - pathElement.getVertex()); - this.prevEdge = edge; - this.prevPathElement = pathElement; - - this.nHops = pathElement.getHopCount() + 1; - } - - /** - * Copy constructor. - * - * @param original source to copy from - */ - protected AbstractPathElement(AbstractPathElement original) - { - this.nHops = original.nHops; - this.prevEdge = original.prevEdge; - this.prevPathElement = original.prevPathElement; - this.vertex = original.vertex; - } - - /** - * Creates an empty path element. - * - * @param vertex end vertex of the path element. - */ - protected AbstractPathElement(V vertex) - { - this.vertex = vertex; - this.prevEdge = null; - this.prevPathElement = null; - - this.nHops = 0; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the path as a list of edges. - * - * @return list of Edge. - */ - public List createEdgeListPath() - { - List path = new ArrayList(); - AbstractPathElement pathElement = this; - - // while start vertex is not reached. - while (pathElement.getPrevEdge() != null) { - path.add(pathElement.getPrevEdge()); - - pathElement = pathElement.getPrevPathElement(); - } - - Collections.reverse(path); - - return path; - } - - /** - * Returns the number of hops (or number of edges) of the path. - * - * @return . - */ - public int getHopCount() - { - return this.nHops; - } - - /** - * Returns the edge reaching the target vertex of the path. - * - * @return null if the path is empty. - */ - public E getPrevEdge() - { - return this.prevEdge; - } - - /** - * Returns the previous path element. - * - * @return null is the path is empty. - */ - public AbstractPathElement getPrevPathElement() - { - return this.prevPathElement; - } - - /** - * Returns the target vertex of the path. - * - * @return . - */ - public V getVertex() - { - return this.vertex; - } -} - -// End AbstractPathElement.java diff --git a/src/org/jgrapht/alg/AbstractPathElementList.java b/src/org/jgrapht/alg/AbstractPathElementList.java deleted file mode 100644 index a81082b..0000000 --- a/src/org/jgrapht/alg/AbstractPathElementList.java +++ /dev/null @@ -1,196 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2010, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * AbstractPathElementList.java - * ------------------------- - * (C) Copyright 2007-2010, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * 06-Dec-2010 : Bugfixes (GB); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * List of paths AbstractPathElement with same target vertex. - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -abstract class AbstractPathElementList> - extends AbstractList -{ - //~ Instance fields -------------------------------------------------------- - - protected Graph graph; - - /** - * Max number of stored paths. - */ - protected int maxSize; - - /** - * Stored paths, list of AbstractPathElement. - */ - protected ArrayList pathElements = new ArrayList(); - - /** - * Target vertex of the paths. - */ - protected V vertex; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates paths obtained by concatenating the specified edge to the - * specified paths. - * - * @param maxSize maximum number of paths the list is able to store. - * @param elementList paths, list of AbstractPathElement. - * @param edge edge reaching the end vertex of the created paths. - * - * @throws NullPointerException if the specified prevPathElementList or edge - * is null. - * @throws IllegalArgumentException if maxSize is negative or - * 0. - */ - protected AbstractPathElementList( - Graph graph, - int maxSize, - AbstractPathElementList elementList, - E edge) - { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize is negative or 0"); - } - if (elementList == null) { - throw new NullPointerException("elementList is null"); - } - if (edge == null) { - throw new NullPointerException("edge is null"); - } - - this.graph = graph; - this.maxSize = maxSize; - this.vertex = - Graphs.getOppositeVertex(graph, edge, elementList.getVertex()); - } - - /** - * Creates a list with an empty path. The list size is 1. - * - * @param maxSize maximum number of paths the list is able to store. - * - * @throws NullPointerException if the specified path-element is - * null. - * @throws IllegalArgumentException if maxSize is negative or - * 0. - * @throws IllegalArgumentException if pathElement is not - * empty. - */ - protected AbstractPathElementList( - Graph graph, - int maxSize, - T pathElement) - { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize is negative or 0"); - } - if (pathElement == null) { - throw new NullPointerException("pathElement is null"); - } - if (pathElement.getPrevEdge() != null) { - throw new IllegalArgumentException("path must be empty"); - } - - this.graph = graph; - this.maxSize = maxSize; - this.vertex = pathElement.getVertex(); - - this.pathElements.add(pathElement); - } - - /** - * Creates an empty list. The list size is 0. - * - * @param maxSize maximum number of paths the list is able to store. - * - * @throws IllegalArgumentException if maxSize is negative or - * 0. - */ - protected AbstractPathElementList(Graph graph, int maxSize, V vertex) - { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize is negative or 0"); - } - - this.graph = graph; - this.maxSize = maxSize; - this.vertex = vertex; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns path AbstractPathElement stored at the specified - * index. - */ - public T get(int index) - { - return this.pathElements.get(index); - } - - /** - * Returns target vertex. - */ - public V getVertex() - { - return this.vertex; - } - - /** - * Returns the number of paths stored in the list. - */ - public int size() - { - return this.pathElements.size(); - } -} - -// End AbstractPathElementList.java diff --git a/src/org/jgrapht/alg/BellmanFordIterator.java b/src/org/jgrapht/alg/BellmanFordIterator.java deleted file mode 100644 index 680add2..0000000 --- a/src/org/jgrapht/alg/BellmanFordIterator.java +++ /dev/null @@ -1,448 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BellmanFordIterator.java - * ------------------------- - * (C) Copyright 2006-2008, by France Telecom and Contributors. - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jan-2006 : Initial revision (GB); - * 14-Jan-2006 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Helper class for {@link BellmanFordShortestPath}; not intended for general - * use. - */ -class BellmanFordIterator - implements Iterator> -{ - //~ Static fields/initializers --------------------------------------------- - - /** - * Error message. - */ - protected final static String NEGATIVE_UNDIRECTED_EDGE = - "Negative" - + "edge-weights are not allowed in an unidrected graph!"; - - //~ Instance fields -------------------------------------------------------- - - /** - * Graph on which shortest paths are searched. - */ - protected Graph graph; - - /** - * Start vertex. - */ - protected V startVertex; - - /** - * Vertices whose shortest path cost have been improved during the previous - * pass. - */ - private List prevImprovedVertices = new ArrayList(); - - private Map> prevVertexData; - - private boolean startVertexEncountered = false; - - /** - * Stores the vertices that have been seen during iteration and (optionally) - * some additional traversal info regarding each vertex. - */ - private Map> vertexData; - - private double epsilon; - - //~ Constructors ----------------------------------------------------------- - - /** - * @param graph - * @param startVertex start vertex. - * @param epsilon tolerance factor. - */ - protected BellmanFordIterator( - Graph graph, - V startVertex, - double epsilon) - { - assertBellmanFordIterator(graph, startVertex); - - this.graph = graph; - this.startVertex = startVertex; - this.epsilon = epsilon; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the path element of the shortest path with less than - * nMaxHops edges between the start vertex and the end vertex. - * - * @param endVertex end vertex. - * - * @return . - */ - public BellmanFordPathElement getPathElement(V endVertex) - { - return getSeenData(endVertex); - } - - /** - * @return true if at least one path has been improved during - * the previous pass, false otherwise. - */ - public boolean hasNext() - { - if (!this.startVertexEncountered) { - encounterStartVertex(); - } - - return !(this.prevImprovedVertices.isEmpty()); - } - - /** - * Returns the list Collection of vertices whose path has been - * improved during the current pass. - * - * @see java.util.Iterator#next() - */ - public List next() - { - if (!this.startVertexEncountered) { - encounterStartVertex(); - } - - if (hasNext()) { - List improvedVertices = new ArrayList(); - for (int i = this.prevImprovedVertices.size() - 1; i >= 0; i--) { - V vertex = this.prevImprovedVertices.get(i); - for ( - Iterator iter = edgesOfIterator(vertex); - iter.hasNext();) - { - E edge = iter.next(); - V oppositeVertex = - Graphs.getOppositeVertex( - graph, - edge, - vertex); - if (getPathElement(oppositeVertex) != null) { - boolean relaxed = - relaxVertexAgain(oppositeVertex, edge); - if (relaxed) { - improvedVertices.add(oppositeVertex); - } - } else { - relaxVertex(oppositeVertex, edge); - improvedVertices.add(oppositeVertex); - } - } - } - - savePassData(improvedVertices); - - return improvedVertices; - } - - throw new NoSuchElementException(); - } - - /** - * Unsupported - * - * @see java.util.Iterator#remove() - */ - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * @param edge - * - * @throws IllegalArgumentException if the graph is undirected and the - * edge-weight is negative. - */ - protected void assertValidEdge(E edge) - { - if (this.graph instanceof UndirectedGraph) { - if (graph.getEdgeWeight(edge) < 0) { - throw new IllegalArgumentException(NEGATIVE_UNDIRECTED_EDGE); - } - } - } - - /** - * Costs taken into account are the weights stored in Edge - * objects. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - * - * @return the cost obtained by concatenation. - * - * @see Graph#getEdgeWeight(E) - */ - protected double calculatePathCost(V vertex, E edge) - { - V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex); - - // we get the data of the previous pass. - BellmanFordPathElement oppositePrevData = - getPrevSeenData(oppositeVertex); - - double pathCost = graph.getEdgeWeight(edge); - - if (!oppositePrevData.getVertex().equals(this.startVertex)) { - // if it's not the start vertex, we add the cost of the previous - // pass. - pathCost += oppositePrevData.getCost(); - } - - return pathCost; - } - - /** - * Returns an iterator to loop over outgoing edges Edge of the - * vertex. - * - * @param vertex - * - * @return . - */ - protected Iterator edgesOfIterator(V vertex) - { - if (this.graph instanceof DirectedGraph) { - return ((DirectedGraph) this.graph).outgoingEdgesOf(vertex) - .iterator(); - } else { - return this.graph.edgesOf(vertex).iterator(); - } - } - - /** - * Access the data stored for a seen vertex in the previous pass. - * - * @param vertex a vertex which has already been seen. - * - * @return data associated with the seen vertex or null if no - * data was associated with the vertex. - */ - protected BellmanFordPathElement getPrevSeenData(V vertex) - { - return this.prevVertexData.get(vertex); - } - - /** - * Access the data stored for a seen vertex in the current pass. - * - * @param vertex a vertex which has already been seen. - * - * @return data associated with the seen vertex or null if no - * data was associated with the vertex. - */ - protected BellmanFordPathElement getSeenData(V vertex) - { - return this.vertexData.get(vertex); - } - - /** - * Determines whether a vertex has been seen yet by this traversal. - * - * @param vertex vertex in question. - * - * @return true if vertex has already been seen. - */ - protected boolean isSeenVertex(V vertex) - { - return this.vertexData.containsKey(vertex); - } - - /** - * @param vertex - * @param data - * - * @return . - */ - protected BellmanFordPathElement putPrevSeenData( - V vertex, - BellmanFordPathElement data) - { - if (this.prevVertexData == null) { - this.prevVertexData = - new HashMap>(); - } - - return this.prevVertexData.put(vertex, data); - } - - /** - * Stores iterator-dependent data for a vertex that has been seen during the - * current pass. - * - * @param vertex a vertex which has been seen. - * @param data data to be associated with the seen vertex. - * - * @return previous value associated with specified vertex or - * null if no data was associated with the vertex. - */ - protected BellmanFordPathElement putSeenData( - V vertex, - BellmanFordPathElement data) - { - if (this.vertexData == null) { - this.vertexData = new HashMap>(); - } - - return this.vertexData.put(vertex, data); - } - - private void assertBellmanFordIterator(Graph graph, V startVertex) - { - if (!(graph.containsVertex(startVertex))) { - throw new IllegalArgumentException( - "Graph must contain the start vertex!"); - } - } - - /** - * The first time we see a vertex, make up a new entry for it. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - * @param cost cost of the created path element. - * - * @return the new entry. - */ - private BellmanFordPathElement createSeenData( - V vertex, - E edge, - double cost) - { - BellmanFordPathElement prevPathElement = - getPrevSeenData( - Graphs.getOppositeVertex(graph, edge, vertex)); - - BellmanFordPathElement data = - new BellmanFordPathElement( - graph, - prevPathElement, - edge, - cost, - epsilon); - - return data; - } - - private void encounterStartVertex() - { - BellmanFordPathElement data = - new BellmanFordPathElement( - this.startVertex, - epsilon); - - // first the only vertex considered as improved is the start vertex. - this.prevImprovedVertices.add(this.startVertex); - - putSeenData(this.startVertex, data); - putPrevSeenData(this.startVertex, data); - - this.startVertexEncountered = true; - } - - /** - * Upates data first time a vertex is reached by a path. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - */ - private void relaxVertex(V vertex, E edge) - { - assertValidEdge(edge); - - double shortestPathCost = calculatePathCost(vertex, edge); - - BellmanFordPathElement data = - createSeenData(vertex, edge, - shortestPathCost); - - putSeenData(vertex, data); - } - - /** - * Check if the cost of the best path so far reaching the specified vertex - * could be improved if the vertex is reached through the specified edge. - * - * @param vertex a vertex which has just been encountered. - * @param edge the edge via which the vertex was encountered. - * - * @return true if the cost has been improved, - * false otherwise. - */ - private boolean relaxVertexAgain(V vertex, E edge) - { - assertValidEdge(edge); - - double candidateCost = calculatePathCost(vertex, edge); - - // we get the data of the previous pass. - BellmanFordPathElement oppositePrevData = - getPrevSeenData( - Graphs.getOppositeVertex(graph, edge, vertex)); - - BellmanFordPathElement pathElement = getSeenData(vertex); - return pathElement.improve(oppositePrevData, edge, candidateCost); - } - - private void savePassData(List improvedVertices) - { - for (V vertex : improvedVertices) { - BellmanFordPathElement orig = getSeenData(vertex); - BellmanFordPathElement clonedData = - new BellmanFordPathElement(orig); - putPrevSeenData(vertex, clonedData); - } - - this.prevImprovedVertices = improvedVertices; - } -} - -// End BellmanFordIterator.java diff --git a/src/org/jgrapht/alg/BellmanFordPathElement.java b/src/org/jgrapht/alg/BellmanFordPathElement.java deleted file mode 100644 index 8b88264..0000000 --- a/src/org/jgrapht/alg/BellmanFordPathElement.java +++ /dev/null @@ -1,150 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BellmanFordPathElement.java - * ------------------------- - * (C) Copyright 2006-2008, by France Telecom and Contributors. - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jan-2006 : Initial revision (GB); - * 14-Jan-2006 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import org.jgrapht.*; - - -/** - * Helper class for {@link BellmanFordShortestPath}; not intended for general - * use. - */ -final class BellmanFordPathElement - extends AbstractPathElement -{ - //~ Instance fields -------------------------------------------------------- - - private double cost = 0; - private double epsilon; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a path element by concatenation of an edge to a path element. - * - * @param pathElement - * @param edge edge reaching the end vertex of the path element created. - * @param cost total cost of the created path element. - * @param epsilon tolerance factor. - */ - protected BellmanFordPathElement( - Graph graph, - BellmanFordPathElement pathElement, - E edge, - double cost, - double epsilon) - { - super(graph, pathElement, edge); - - this.cost = cost; - this.epsilon = epsilon; - } - - /** - * Copy constructor. - * - * @param original source to copy from - */ - BellmanFordPathElement(BellmanFordPathElement original) - { - super(original); - this.cost = original.cost; - this.epsilon = original.epsilon; - } - - /** - * Creates an empty path element. - * - * @param vertex end vertex of the path element. - * @param epsilon tolerance factor. - */ - protected BellmanFordPathElement(V vertex, double epsilon) - { - super(vertex); - - this.cost = 0; - this.epsilon = epsilon; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the total cost of the path element. - * - * @return . - */ - public double getCost() - { - return this.cost; - } - - /** - * Returns true if the path has been improved, - * false otherwise. We use an "epsilon" precision to check whether - * the cost has been improved (because of many roundings, a formula equal to - * 0 could unfortunately be evaluated to 10^-14). - * - * @param candidatePrevPathElement - * @param candidateEdge - * @param candidateCost - * - * @return . - */ - protected boolean improve( - BellmanFordPathElement candidatePrevPathElement, - E candidateEdge, - double candidateCost) - { - // to avoid improvement only due to rounding errors. - if (candidateCost < (getCost() - epsilon)) { - this.prevPathElement = candidatePrevPathElement; - this.prevEdge = candidateEdge; - this.cost = candidateCost; - this.nHops = candidatePrevPathElement.getHopCount() + 1; - - return true; - } else { - return false; - } - } -} - -// End BellmanFordPathElement.java diff --git a/src/org/jgrapht/alg/BellmanFordShortestPath.java b/src/org/jgrapht/alg/BellmanFordShortestPath.java deleted file mode 100644 index dcce9ff..0000000 --- a/src/org/jgrapht/alg/BellmanFordShortestPath.java +++ /dev/null @@ -1,239 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BellmanFordShortestPath.java - * ------------------------- - * (C) Copyright 2006-2008, by France Telecom and Contributors. - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jan-2006 : Initial revision (GB); - * 14-Jan-2006 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Bellman-Ford - * algorithm: weights could be negative, paths could be constrained by a - * maximum number of edges. - */ -public class BellmanFordShortestPath -{ - //~ Static fields/initializers --------------------------------------------- - - private static final double DEFAULT_EPSILON = 0.000000001; - - //~ Instance fields -------------------------------------------------------- - - /** - * Graph on which shortest paths are searched. - */ - protected Graph graph; - - /** - * Start vertex. - */ - protected V startVertex; - - private BellmanFordIterator iter; - - /** - * Maximum number of edges of the calculated paths. - */ - private int nMaxHops; - - private int passNumber; - - private double epsilon; - - //~ Constructors ----------------------------------------------------------- - - /** - * Creates an object to calculate shortest paths between the start vertex - * and others vertices using the Bellman-Ford algorithm. - * - * @param graph - * @param startVertex - */ - public BellmanFordShortestPath(Graph graph, V startVertex) - { - this(graph, startVertex, graph.vertexSet().size() - 1); - } - - /** - * Creates an object to calculate shortest paths between the start vertex - * and others vertices using the Bellman-Ford algorithm. - * - * @param graph - * @param startVertex - * @param nMaxHops maximum number of edges of the calculated paths. - */ - public BellmanFordShortestPath( - Graph graph, - V startVertex, - int nMaxHops) - { - this(graph, startVertex, nMaxHops, DEFAULT_EPSILON); - } - - /** - * Creates an object to calculate shortest paths between the start vertex - * and others vertices using the Bellman-Ford algorithm. - * - * @param graph - * @param startVertex - * @param nMaxHops maximum number of edges of the calculated paths. - * @param epsilon tolerance factor. - */ - public BellmanFordShortestPath( - Graph graph, - V startVertex, - int nMaxHops, - double epsilon) - { - this.startVertex = startVertex; - this.nMaxHops = nMaxHops; - this.graph = graph; - this.passNumber = 1; - this.epsilon = epsilon; - } - - //~ Methods ---------------------------------------------------------------- - - /** - * @param endVertex end vertex. - * - * @return the cost of the shortest path between the start vertex and the - * end vertex. - */ - public double getCost(V endVertex) - { - assertGetPath(endVertex); - - lazyCalculate(); - - BellmanFordPathElement pathElement = - this.iter.getPathElement(endVertex); - - if (pathElement == null) { - return Double.POSITIVE_INFINITY; - } - - return pathElement.getCost(); - } - - /** - * @param endVertex end vertex. - * - * @return list of Edge, or null if no path exists between the - * start vertex and the end vertex. - */ - public List getPathEdgeList(V endVertex) - { - assertGetPath(endVertex); - - lazyCalculate(); - - BellmanFordPathElement pathElement = - this.iter.getPathElement(endVertex); - - if (pathElement == null) { - return null; - } - - return pathElement.createEdgeListPath(); - } - - private void assertGetPath(V endVertex) - { - if (endVertex.equals(this.startVertex)) { - throw new IllegalArgumentException( - "The end vertex is the same as the start vertex!"); - } - - if (!this.graph.containsVertex(endVertex)) { - throw new IllegalArgumentException( - "Graph must contain the end vertex!"); - } - } - - private void lazyCalculate() - { - if (this.iter == null) { - this.iter = - new BellmanFordIterator( - this.graph, - this.startVertex, - epsilon); - } - - // at the i-th pass the shortest paths with less (or equal) than i edges - // are calculated. - for ( - ; - (this.passNumber <= this.nMaxHops) && this.iter.hasNext(); - this.passNumber++) - { - this.iter.next(); - } - } - - /** - * Convenience method to find the shortest path via a single static method - * call. If you need a more advanced search (e.g. limited by hops, or - * computation of the path length), use the constructor instead. - * - * @param graph the graph to be searched - * @param startVertex the vertex at which the path should start - * @param endVertex the vertex at which the path should end - * - * @return List of Edges, or null if no path exists - */ - public static List findPathBetween( - Graph graph, - V startVertex, - V endVertex) - { - BellmanFordShortestPath alg = - new BellmanFordShortestPath( - graph, - startVertex); - - return alg.getPathEdgeList(endVertex); - } -} - -// End BellmanFordShortestPath.java diff --git a/src/org/jgrapht/alg/BiconnectivityInspector.java b/src/org/jgrapht/alg/BiconnectivityInspector.java deleted file mode 100644 index 3e1c1ca..0000000 --- a/src/org/jgrapht/alg/BiconnectivityInspector.java +++ /dev/null @@ -1,138 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BiconnectivityInspector.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; - - -/** - * Inspects a graph for the biconnectivity property. See {@link - * BlockCutpointGraph} for more information. A biconnected graph has only one - * block (i.e. no cutpoints). - * - * @author Guillaume Boulmier - * @since July 5, 2007 - */ -public class BiconnectivityInspector -{ - //~ Instance fields -------------------------------------------------------- - - private BlockCutpointGraph blockCutpointGraph; - - //~ Constructors ----------------------------------------------------------- - - /** - * Running time = O(m) where m is the number of edges. - */ - public BiconnectivityInspector(UndirectedGraph graph) - { - super(); - this.blockCutpointGraph = new BlockCutpointGraph(graph); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Returns the biconnected vertex-components of the graph. - */ - public Set> getBiconnectedVertexComponents() - { - Set> biconnectedVertexComponents = new HashSet>(); - for ( - Iterator> iter = - this.blockCutpointGraph.vertexSet().iterator(); - iter.hasNext();) - { - UndirectedGraph subgraph = iter.next(); - if (!subgraph.edgeSet().isEmpty()) { - biconnectedVertexComponents.add(subgraph.vertexSet()); - } - } - - return biconnectedVertexComponents; - } - - /** - * Returns the biconnected vertex-components containing the vertex. A - * biconnected vertex-component contains all the vertices in the component. - * A vertex which is not a cutpoint is contained in exactly one component. A - * cutpoint is contained is at least 2 components. - * - * @param vertex - * - * @return set of all biconnected vertex-components containing the vertex. - */ - public Set> getBiconnectedVertexComponents(V vertex) - { - Set> vertexComponents = new HashSet>(); - for ( - Iterator> iter = getBiconnectedVertexComponents().iterator(); - iter.hasNext();) - { - Set vertexComponent = iter.next(); - if (vertexComponent.contains(vertex)) { - vertexComponents.add(vertexComponent); - } - } - return vertexComponents; - } - - /** - * Returns the cutpoints of the graph. - */ - public Set getCutpoints() - { - return this.blockCutpointGraph.getCutpoints(); - } - - /** - * Returns true if the graph is biconnected (no cutpoint), - * false otherwise. - */ - public boolean isBiconnected() - { - return this.blockCutpointGraph.vertexSet().size() == 1; - } -} - -// End BiconnectivityInspector.java diff --git a/src/org/jgrapht/alg/BlockCutpointGraph.java b/src/org/jgrapht/alg/BlockCutpointGraph.java deleted file mode 100644 index 5ea029c..0000000 --- a/src/org/jgrapht/alg/BlockCutpointGraph.java +++ /dev/null @@ -1,365 +0,0 @@ -/* ========================================== - * JGraphT : a free Java graph-theory library - * ========================================== - * - * Project Info: http://jgrapht.sourceforge.net/ - * Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh) - * - * (C) Copyright 2003-2008, by Barak Naveh and Contributors. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ -/* ------------------------- - * BlockCutpointGraph.java - * ------------------------- - * (C) Copyright 2007-2008, by France Telecom - * - * Original Author: Guillaume Boulmier and Contributors. - * Contributor(s): John V. Sichi - * - * $Id$ - * - * Changes - * ------- - * 05-Jun-2007 : Initial revision (GB); - * 05-Jul-2007 : Added support for generics (JVS); - * - */ -package org.jgrapht.alg; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - - -/** - * Definition of a block of a - * graph in MathWorld.
      - *
      Definition and lemma taken from the article - * Structure-Based Resilience Metrics for Service-Oriented Networks: - * - *